Введение#
Выбор правильной структуры данных — это фундаментальный шаг при проектировании производительного приложения. В стандартной библиотеке Rust модуль std::collections предоставляет четыре основные категории контейнеров: последовательности, словари, множества и очереди с приоритетом.
Каждый из них по-своему организует память и предлагает разные алгоритмические гарантии (O(1), O(log N), O(N)). Кроме того, в современных процессорах огромное значение имеет кэш-дружелюбность (Cache Friendliness) — то, насколько элементы расположены непрерывно в оперативной памяти.
В этой статье мы подробно разберем продвинутые коллекции std::collections — VecDeque, BTreeMap, BTreeSet и BinaryHeap —, сравним их архитектуру и разберем правила выбора контейнера под вашу задачу.
1. Последовательности: VecDeque vs Vec vs LinkedList#
Динамический массив (Vec<T>)#
Классический Vec<T> — это непрерывный блок памяти в куче. За счет последовательного расположения элементов он обеспечивает невероятно быструю итерацию и доступ по индексу за O(1).
Однако удаление или вставка элементов в начало или середину Vec требует сдвига всех последующих элементов за O(N).
Двусторонняя очередь (VecDeque<T>)#
Когда вам требуется эффективная очередь FIFO (First In, First Out) или стек, на помощь приходит VecDeque<T>.
Он реализован как кольцевой буфер (Ring Buffer) над динамическим массивом:
- Добавление/удаление с конца (
push_back/pop_back) —O(1). - Добавление/удаление с начала (
push_front/pop_front) —O(1).
В 99% случаев, если вам нужен список задач или очередь сообщений, VecDeque будет значительно быстрее и память-эффективнее, чем связный список LinkedList.
Связный список (LinkedList<T>)#
Стандартный двунаправленный связный список LinkedList<T> в Rust используется крайне редко. Из-за того, что каждый узел аллоцируется в куче отдельно, при итерации происходит огромное количество промахов мимо кэша процессора (Cache Misses).
2. Словари и множества: BTreeMap vs HashMap#
При работе с ассоциативными массивами (парами «ключ-значение») в Rust есть два принципиально разных подхода.
Хеш-таблицы (HashMap<K, V> и HashSet<T>)#
- Архитектура: Исполнены на основе алгоритма SwissTable.
- Сложность: Поиск, вставка и удаление в среднем выполняются за
O(1). - Особенности: Порядок элементов внутри
HashMapслучайный и неопределенный. Требуют реализации типажаHash + Eqдля ключей.
B-деревья (BTreeMap<K, V> и BTreeSet<T>)#
- Архитектура: Организованы как B-дерево, где каждый узел содержит небольшой массив элементов для эффективной работы с L1/L2 кэшем процессора.
- Сложность: Поиск, вставка и удаление выполняются за
O(log N). - Особенности: Ключи всегда отсортированы. Требуют реализации типажа
Ordдля ключей.
use std::collections::BTreeMap;
let mut map = BTreeMap::new();
map.insert(3, "Третий");
map.insert(1, "Первый");
// Итерация гарантированно выведет: 1 -> Первый, 3 -> Третий
for (key, val) in &map {
println!("{key}: {val}");
}Зачем использовать BTreeMap, если HashMap работает за O(1)?
- Вам нужна сортировка ключей «из коробки».
- Вам требуется делать срезы и диапазонные запросы через
.range(min..max). - Вам нужны предсказуемые логарифмические гарантии без риска худшего случая
O(N)при коллизиях хешей.
3. Очередь с приоритетом: BinaryHeap#
BinaryHeap<T> — это коллекция, реализованная на основе двоичной Max-Кучи (Max-Heap) поверх динамического массива.
Она предназначена для планировщиков задач и обработчиков событий, где элементы должны извлекаться строго по степени их важности.
- Вызов
.push(item)добавляет элемент заO(log N). - Вызов
.pop()всегда извлекает наибольший элемент заO(log N). - Просмотр наибольшего элемента
.peek()выполняется заO(1).
Чтобы превратить BinaryHeap в Min-Кучу (где первым извлекается наименьший элемент), достаточно обернуть элементы в стандартный контейнер std::cmp::Reverse(x).
4. Сводная шпаргалка алгоритмической сложности#
| Коллекция | Поиск по ключу/индексу | Вставка в начало | Вставка в конец | Сортировка элементов |
|---|---|---|---|---|
Vec<T> | O(1) по индексу | O(N) | O(1) amortized | ❌ Нет |
VecDeque<T> | O(1) по индексу | O(1) amortized | O(1) amortized | ❌ Нет |
HashMap<K, V> | O(1) avg | — | — | ❌ Нет |
BTreeMap<K, V> | O(log N) | — | — | ✅ Автоматически |
BinaryHeap<T> | O(1) для Max | — | O(log N) | 🔝 Приоритетная |
Давайте изучим эти коллекции на практических слайдах:
Проверь свои знания!#
Пройдите короткий тест, чтобы проверить знания особенностей коллекций в Rust:


