В далеком 1976 году швейцарским ученым была написана книга «Алгоритмы + Структуры данных = Программы». Прошло уже более сорока лет, но это утверждение до сих пор актуально.  Вы должны знать структуры данных, если учите языки программирования и желаете стать разработчиком. И не только знать, но и уметь их применять. Причем не столь важно, закончили ли вы институт либо просто освоили курсы программирования, — на собеседовании при устройстве на работу у вас в 90 % случаев спросят про структуры данных.

Этот материал — адаптированный перевод статьи «The top data structures you should know for your next coding interview». В этом переводе будут вкратце рассмотрены основные структуры данных, которые могут понадобиться при программировании, плюс будут перечислены наиболее популярные вопросы, которые часто задают на собеседованиях.

Изучаем структуры данных: что это?

Если говорить простым языком, то структура данных представляет собой контейнер, в котором информация скомпонована специальным образом. Чего удается достичь благодаря такому строению? Для сравнения, скажем, что при выполнении одних операций определенная структура данных будет весьма эффективна, в то время как при выполнении других — не очень. Задача разработчика вне зависимости от языка программирования (language of programming) как раз в том и состоит, чтобы уметь выбирать наиболее подходящую структуру и знать, как сравнить их между собой с учетом поставленной задачи. Но это невозможно без ясного и единого представления о существующих способах организации информации. Именно это единое представление вы и получите в процессе изучения материалов этой статьи. И займет это совсем немного времени.

Изучаем структуры данных: зачем вообще они нужны?

Структура позволяет хранить информацию в упорядоченном виде, а информация — это основополагающий термин информатики, что понятно даже, исходя из словообразования. И не так уж важно, какую конкретно задачу решает программист: таки или иначе он все равно будет иметь дело с обработкой данных, причем хранить их надо будет то в одном формате, то в другом.

Изучаем структуры данных: топ-8

Ниже перечислены самые распространенные способы структурирования данных:

  1. Массивы.
  2. Очереди.
  3. Стеки.
  4. Деревья.
  5. Связные списки.
  6. Графы.
  7. Боры.
  8. Хэш-таблицы.

Массивы

Самый распространенный способ структуризации. Ниже показан простейший массив из 4-х элементов:

Топ-8 структур данных для программиста


Каждый элемент имеет числовое значение (индекс), которое соответствует положению элемента в массиве. Обычно в языках программирования нумерация начинается не с единицы, а с нуля.

Массивы бывают:

— одномерные (как на картинке);

— многомерные.

Простейшие операции:

  • Insert — вставка элемента на позицию с заданным индексом;
  • Get — возвращение элемента, занимающего позицию с заданным индексом;
  • Delete — удаление;
  • Size — получение общего числа элементов.

Какие вопросы, связанные с массивам, часто задают на собеседовании:

  • найдите 2-й минимальный элемент;
  • найдите неповторяющиеся целые числа;
  • выполните объединение двух отсортированных массивов;
  • выполните упорядочение положительных и отрицательных значений.

Стеки

Стек обычно сравнивают со стопкой книг. Когда нужно взять какую-либо книгу, к примеру, лежащую в центре стопки, вам надо сначала снять те книги, которые лежат выше. Это известный принцип LIFO (кто последний пришел, тот первый выйдет).

На картинке ниже — стек, который содержит 3 элемента:

Топ-8 структур данных для программиста

Простейшие операции:

  • Push — вставка элемента в стек сверху;
  • Pop — возвращение верхнего компонента в стек после удаления;
  • isEmpty — возвращение true, когда стек пуст;
  • Top — возвращение верхнего компонента без удаления его из стека.

Вопросы о стеке:

  • вычислите постфиксное выражение посредством стека;
  • отсортируйте значения;
  • проверьте сбалансированные скобки в выражении.

Очереди

Очередь представляет собой линейную структура данных, где элементы хранятся последовательно. Однако при сравнении со стеком мы увидим, что здесь действует уже принцип FIFO (первый пришел — первый вышел). Классический пример — очередь покупателей в гипермаркете.

Изображение очереди:

Топ-8 структур данных для программиста

Операции:

  • Enqueue() — добавление элемента в конец очереди;
  • Dequeue() — удаление элемента из начала;
  • isEmpty() — возвращение true, если очередь пуста;
  • Top() — возвращение первого элемента.

Вопросы:

  • реализовать стек посредством очереди;
  • обратить первые k-элементы в очереди;
  • сгенерировать двоичные числа от 1 до n, используя очередь.

Связный список

Эта структура напоминает массив, но если выполнить сравнение, становится понятно, что связный список отличается по ряду характеристик:

— выделение памяти;

— внутренняя структура;

— особенности вставки и удаления.

Связный список можно назвать цепочкой узлов, причем каждый из них содержит информацию: к примеру, данные и указатель на последующий узел в цепочке. Существует головной указатель, который соответствует первому элементу в списке, а если список пуст, то указатель направлен на null.

Применение — реализация файловых систем, хэш-таблицы, списки смежности.

Топ-8 структур данных для программиста

Типы:

  • односвязный (однонаправленный);
  • двусвязный (двунаправленный).

Простейшие действия:

  • InsertAtEnd — вставка заданного элемента в конец;
  • InsertAtHead — вставка в начало (с головы);
  • Delete — удаление из списка;
  • DeleteAtHead — удаление первого компонента;
  • Search — возвращение заданного компонента из списка;
  • isEmpty — возвращение true, если имеющийся список пуст.

Вопросы:

  • обратить связный список;
  • найти петлю;
  • вернуть N-ный узел с начала списка;
  • удалить дублирующиеся значения.

Графы

Графом называют множество узлов, которые соединены друг с другом, образуя сеть. Узлы = вершины. Пара (x, y) — это ребро, которое может иметь стоимость или вес, что характеризует, насколько затратным является переход от одной вершины к другой.

Топ-8 структур данных для программиста

Типы:

  • неориентированные;
  • ориентированные.

В языке программирования популярны графы 2-х типов:

  • матрица смежности;
  • список смежности.

Также надо знать самые популярные алгоритмы обхода графа:

  • поиск в ширину;
  • поиск в глубину.

Вопросы к собеседованию, которые желательно проработать:

  • реализация поиска в ширину и глубину;
  • проверка, является ли граф деревом;
  • подсчет числа ребер;
  • поиск кратчайшего пути между 2-мя вершинами.

Деревья

Деревья — иерархическая структура, которые состоят из вершин и ребер, соединяющих эти вершины. Мы можем сказать, что деревья подобны графам, но тут существует различие: у первых не бывает циклов.

Сегодня деревья применяются в сфере ИИ, а также в сложных алгоритмах, где они выступают в роли эффективного хранилища данных. С деревом знаком, по сути, любой программист.

Ниже — рисунок простого дерева:

Топ-8 структур данных для программиста

Деревья бывают разных типов:

  • N-арное;
  • сбалансированное;
  • двоичное;
  • двоичное дерево поиска;
  • АВЛ-дерево;
  • красно-черное дерево;
  • 2—3 дерево.

Сегодня широко используют двоичные деревья.

На собеседовании у вас могут попросить найти:

  • высоту двоичного дерева;
  • k-ное максимальное значение в 2-чном древе поиска;
  • узлы, которые расположены на расстоянии “k” от корня;
  • предки заданной вершины в 2-чном дереве.

Бор

Второе название — «префиксное дерево». Речь идет о древовидной структуре, которая весьма эффективна в процессе решении задач на строки. Бор обеспечивает быстрое извлечение информации и часто используется при поиске слов в словаре, автоматических завершений в поисковике, а также в IP-маршрутизации.

Давайте посмотрим, как 3 слова «top», «thus» и «their» хранятся в бору:

Топ-8 структур данных для программиста

Вопросы:

  • подсчет общего числа слов, которые сохранены в бору;
  • вывод на экран всех слов, сохраненных в бору;
  • сортировка элементов массива посредством бора;
  • построение слова из словаря;
  • создание словаря T9.

Хэш-таблица

Хэширование используется в целях уникальной идентификации и сохранения объектов по вычисленному индексу, который называют «ключом». В результате объект хранится в формате «ключ-значение», а коллекция этих объектов представляет собой «словарь». Поиск объекта осуществляется по его ключу. Есть разные структуры данных, которые построены по принципам хэширования, к примеру, широко известна хэш-таблица (обычно ее реализуют посредством массивов).
От чего зависит производительность хэширующей структуры:

  • от хэш-функции;
  • от размера хэш-таблицы;
  • от метода обработки коллизий.
Топ-8 структур данных для программиста

Что могут спросить:

  • поиск симметричных пар;
  • отслеживание полной траектории пути;
  • поиск, является ли массив подмножеством другого массива;
  • проверка, можно ли назвать массивы непересекающимися.

Надеемся, этот перевод был вам полезен, и теперь вы имеете единое понимание основных структур данных, которые должен знать каждый разработчик. Мы уверены, что предоставленная информация обязательно поможет на собеседовании по программированию. Успехов!