kata academy

Что такое структура данных и как с ней работать? Примеры и объяснения


Подробный разбор базовых структур с примерами кода на Java и Go.

Время чтения: 5 минут
Хочешь кодить как босс?
Заполняй форму и начни свой путь в IT прямо сейчас!
Что такое структура данных в программировании?
Структура данных — это способ хранения и организации информации в программе. Она помогает компьютеру работать с данными быстро и эффективно.

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

В программировании всё так же. Структура данных говорит, как и где хранить информацию, чтобы потом удобно и быстро её использовать.
Зачем нужны структуры данных?
Ты можешь сказать: «Я и так могу хранить числа или строки в переменных. Зачем мне что-то ещё?». Когда данных становится много, работать с ними вручную становится неудобно. Особенно если тебе нужно:

  • быстро найти нужный элемент,
  • удалить или изменить данные,
  • добавить новые,
  • отсортировать информацию.
Хорошо подобранная структура данных может сделать твою программу в десятки или даже сотни раз быстрее и эффективнее.
IT-калькулятор зарплат
Узнай свою рыночную зарплату за 1 минуту!
Основные (базовые) структуры данных
Массив (Array)
Что такое массив?

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

Есть два вида массивов:
  • Одномерные: обычный список элементов в виде линейной последовательности элементов одного типа.
  • Многомерные: это массивы внутри массивов, их можно представить как таблицу со строками и столбцами (или массив массивов). И что немаловажно, каждый массив может иметь свою длину.

Где применяются массивы?

Массивы — это основа. На них строятся почти все другие структуры данных, такие как списки, стек, очередь и даже матрицы и графы. Их используют, когда нужно хранить упорядоченный набор данных и получать быстрый доступ по индексу. Например:
  • веб-приложения — хранение списка товаров в корзине;
  • игры — список объектов на экране (игроки, враги, бонусы);
  • мобильные приложения — массивы с данными для интерфейса (например, список сообщений);
  • обработка изображений и звука — пиксели, частоты и кадры хранятся как массивы чисел;
  • работа с данными из базы — загрузка и обработка массивов строк или чисел.

Как выглядит массив в коде (одномерный)?

Пример на Java
int[] numbers = {10, 20, 30, 40};
System.out.println(numbers[0]); // выведет 10

Пример на Go
numbers := []int{10, 20, 30, 40}
fmt.Println(numbers[0]) // выведет 10
Пройди курс по Java и получи новую работу всего за 9 месяцев! Мы гарантируем трудоустройство с зарплатой на старте от 120 000 рублей. Более 4500 выпускников уже получили оффер мечты, у тебя тоже получится!
Словарь (Map)
Что такое словарь?

Словарь — это как ящик с ярлыками, где к каждому ярлыку привязано определённое значение. В отличие от массива, где ты ищешь данные по номеру, здесь ты ищешь их по имени. У каждого значения есть ключ — это как надпись на ярлыке. Например:
  • по ключу «имя» лежит значение «Анна»,
  • по ключу «город» — «Москва».
Пример из жизни: представь, что у тебя есть записная книжка. Ты открываешь её на имени «Олег» и сразу находишь его номер телефона. Тебе не нужно помнить номер страницы — ты ищешь по имени.
Точно так же работает словарь в программировании, например, в Go ты пишешь user["name"], а в Java — user.get("name") — и получаешь нужные данные.

Где применяются словари?

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

Как выглядит словарь в коде?

Пример на Java
import java.util.HashMap;
import java.util.Map;

Map<String, String> user = new HashMap<>();
user.put("name", "Anna");
user.put("city", "Moscow");
System.out.println(user.get("city")); // выведет Moscow

Пример на Go
user := map[string]string{
"name": "Anna",
"city": "Moscow",
}
fmt.Println(user["city"]) // выведет Moscow
Очередь (Queue)
Что такое очередь?

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

Представь, что ты стоишь в очереди за билетами:
  • первый человек подходит к кассе и уходит;
  • второй становится первым, и так далее.
В программировании очередь работает точно так же: ты добавляешь элементы в конец очереди, а обрабатываешь их — с начала.

Где применяются очереди?

Очереди особенно полезны, когда задачи нужно выполнять строго в порядке поступления. Например:
  • чат-приложения — новые сообщения попадают в очередь на обработку;
  • сервера — запросы от пользователей обрабатываются по очереди;
  • игры — очередь действий персонажа или врагов;
  • почтовые рассылки — письма отправляются по одному, в порядке поступления;
  • фоновые задачи — например, обработка видео или изображений после загрузки.

Как выглядит очередь в коде?

Пример на Java
import java.util.LinkedList;

import java.util.Queue;

Queue<String> queue = new LinkedList<>();
queue.add("task1");
queue.add("task2");

System.out.println(queue.poll()); // выведет и удалит task1
System.out.println(queue.poll()); // выведет и удалит task2

Пример на Go
В Go нет встроенного типа «очередь», но срез (slice) легко позволяет её реализовать.
queue := []string{}
queue = append(queue, "task1")
queue = append(queue, "task2")

first := queue[0]
queue = queue[1:]

fmt.Println(first) // выведет task1
Твой первый оффер: зарплата от 120 000 рублей! Пройди курс по Go-разработке с гарантией трудоустройства и получи такое предложение от работодателя! Основная оплата курса проходит уже после выхода на работу, ты платишь за полученный результат!

Стек (Stack)
Что такое стек?

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

Точно так же работает стек: ты добавляешь данные в конец стека, и при извлечении получаешь то, что добавил последним. Этот принцип называется LIFO — Last In, First Out (последним пришёл — первым ушёл).

Где применяются стеки?

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

Пример на Java
import java.util.Stack;

Stack<String> stack = new Stack<>();
stack.push("A");
stack.push("B");

System.out.println(stack.pop()); // выведет B
System.out.println(stack.pop()); // выведет A

Пример на Go
Обрати внимание, что в Go, как и с очередью, стек можно реализовать с помощью срезов (slice).
stack := []string{}
stack = append(stack, "A")
stack = append(stack, "B")

last := stack[len(stack)-1]
stack = stack[:len(stack)-1]
fmt.Println(last) // выведет B
Множество (Set)
Что такое множество?

Множество — это как коробка, в которую можно складывать уникальные вещи. Только уникальные! То есть если ты положишь туда одну и ту же вещь дважды, в коробке всё равно будет только одна копия.

В отличие от массива или списка, множество не сохраняет порядок элементов и автоматически убирает дубликаты.

Где применяются множества?

Множества особенно полезны, когда нужно убрать повторы или проверять наличие элемента. Например:

  • проверка уникальных пользователей — чтобы не было повторной регистрации;
  • удаление дубликатов из списка email-адресов;
  • фильтрация тегов или категорий — оставляем только уникальные;
  • игры — список уже собранных предметов (без повторов);
  • проверка, есть ли значение в наборе — например, входит ли число в разрешённый список.
Как выглядит множество в коде?

Пример на Java
import java.util.HashSet;
import java.util.Set;

Set<String> colors = new HashSet<>();
colors.add("red");
colors.add("blue");

colors.add("red"); // второй "red" не добавится

System.out.println(colors.contains("blue")); // выведет true

Пример на Go
В Go нет встроенного типа множество, но его легко реализовать с помощью map. Такой map работает как множество: если ключ есть — значит, элемент в множестве присутствует.

set := make(map[string]bool)
set["red"] = true
set["blue"] = true
set["red"] = true // повтор не повлияет

fmt.Println(set["blue"]) // выведет true
Связанный список (Linked list)
Что такое связанный список?

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

Так работает связанный список:
  • один элемент содержит данные и указатель на следующий элемент;
  • первый элемент называется головой списка;
  • последний элемент никуда не ссылается — он конец списка.

В отличие от массива, связанный список не хранит всё подряд в памяти. Каждый элемент «знает» только о своём соседе, но не о всех остальных.

Где применяются связанные списки?

Связанные списки полезны, когда тебе нужно часто вставлять или удалять элементы в середине структуры, особенно если ты не знаешь заранее её размер. Например:
  • работа со звуковыми или видеофреймами — когда нужно подгружать/удалять куски потока;
  • реализация очередей и стеков под капотом;
  • построение редакторов текста — строки или символы могут быть связаны между собой;
  • история действий (undo/redo) — список изменений, связанных по порядку;
  • управление памятью — когда данные приходят по частям и заранее неясен их объём.
Как выглядит связанный список в коде?

Пример на Java
import java.util.LinkedList;

LinkedList<String> list = new LinkedList<>();
list.add("first");
list.add("second");
list.add("third");

System.out.println(list.getFirst()); // выведет first
System.out.println(list.getLast());// выведет third

Пример на Go
В стандартной библиотеке Go есть реализация двусвязного списка — container/list.
import (
"container/list"
"fmt"
)
func main() {
l := list.New()
l.PushBack("first")
l.PushBack("second")
l.PushBack("third")

fmt.Println(l.Front().Value) // выведет first
fmt.Println(l.Back().Value) // выведет third
}
Более сложные структуры
Для старта работы тебе будет достаточно базовых структур, но с опытом можно добавлять более сложные варианты.

Дерево (Tree) — это структура, похожая на семейное древо, где один элемент — «корень», а остальные — его потомки; используется для хранения иерархических данных, например, в меню или файловых системах.

Двоичное дерево поиска (Binary Search Tree) — это вид дерева, где каждый узел имеет максимум двух потомков, а данные упорядочены так, чтобы можно было быстро искать, добавлять и удалять значения.

Граф (Graph) — это набор объектов (вершин), соединённых линиями (рёбрами); используется для моделирования связей — например, дорог между городами или друзей в соцсетях.

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

Хеш-таблица (Hash Table) — это структура, которая хранит пары «ключ — значение» и позволяет очень быстро находить данные по ключу, даже если их много.
Как научиться программировать и устроиться на работу?
Ты уже начал изучать программирование и понял, что хотел бы работать в этой сфере? Мы рекомендуем перейти на обучение с ментором. Это поможет тебе разобраться даже в самых сложных темах и повысить свои шансы на трудоустройство. Обучение с личным ментором и поддержкой карьерного консультанта есть в Kata Academy. Школа предоставляет гарантию трудоустройства. Узнать подробности можно на сайте.

Статьи для старта в IT

Истории наших выпускников

Стань тем, кто задаёт тон в IT!
Подпишись на нашу рассылку и первым получай статьи по Java, JavaScript, Golang и QA. Позволь себе быть экспертом!