Ответ
std::deque (double-ended queue, дек) — это контейнер стандартной библиотеки C++, который обеспечивает эффективную вставку и удаление элементов как в начало, так и в конец за амортизированное O(1).
Ключевые особенности и отличия от std::vector:
| Особенность | std::deque |
std::vector |
|---|---|---|
| Вставка в начало | O(1) (амортизир.) | O(n) (сдвиг всех элементов) |
| Расположение в памяти | Не гарантирует непрерывность (блочная структура) | Гарантирует непрерывность |
| Инвалидация указателей/итераторов | При модификации инвалидируются все итераторы, указатели/ссылки на элементы — нет (кроме удалённого элемента) | При любом изменении ёмкости инвалидируются все итераторы, указатели и ссылки |
Пример использования:
#include <deque>
#include <iostream>
#include <algorithm> // for std::copy
int main() {
std::deque<int> dq = {2, 3, 4};
// Эффективная вставка с двух сторон
dq.push_front(1); // dq: [1, 2, 3, 4]
dq.push_back(5); // dq: [1, 2, 3, 4, 5]
// Прямой доступ по индексу за O(1)
std::cout << "Element at index 2: " << dq[2] << 'n'; // Выведет: 3
// Итерация
for (const auto& elem : dq) {
std::cout << elem << ' ';
}
// Выведет: 1 2 3 4 5
// Типичный use-case: реализация очереди с возможностью "заглянуть" в начало и конец
// или скользящего окна (sliding window).
return 0;
}
Внутренняя реализация: Обычно реализуется как массив указателей на фиксированные блоки памяти. Это компромисс, дающий быстрые операции с концами, но делающий произвольный доступ и итерацию чуть медленнее, чем у вектора, из-за дополниного уровня косвенности.
Когда использовать: Когда нужна очередь (std::queue по умолчанию использует deque) или требуется часто добавлять/удалять элементы с обоих концов, при этом не критична непрерывность данных в памяти.
Ответ 18+ 🔞
А, std::deque! Ну это же классика, ёпта. Представь себе не какой-то там простой вектор, а такую... хитрожопую двухстороннюю очередь. В рот меня чих-пых, это как если бы у тебя был мешок, куда ты можешь совать вещи и с горла, и с донышка, и всё это за амортизированное O(1). Удобно, блядь.
А теперь смотри, в чём его главный фокус против std::vector. Вектор — он как прямой пацан, все элементы в памяти стоят плечом к плечу, непрерывно. А вот deque — это уже мудя посерьёзнее. Он внутри себя держит несколько блоков памяти, и когда ты что-то в начало пихаешь, он не начинает, как дурак, весь массив на два шага сдвигать. Нет, он просто новый блок заводит или в старом свободное место ищет. Поэтому push_front у него — огонь, а у вектора — полный пиздец, O(n).
Вот тебе табличка, чтобы совсем уж охуеть от контраста:
| Что сравниваем | std::deque |
std::vector |
|---|---|---|
| Засунуть в начало | O(1) (быстро, блядь) | O(n) (медленно, все элементы двигать) |
| В памяти как лежит | Блоками, не гарантирует, что всё подряд | Гарантированно одним куском |
| Итераторы/указатели | При вставке/удалении могут все полететь, но ссылки на сами элементы — обычно живы (кроме того, что удалил) | Любое изменение capacity — и всё, пидарас шерстяной, все итераторы и ссылки в помойку |
Ну и примерчик, чтобы пальцы по клаве постучать:
#include <deque>
#include <iostream>
#include <algorithm> // для std::copy
int main() {
std::deque<int> dq = {2, 3, 4};
// Вот она, магия — пихаем с двух сторон без боли
dq.push_front(1); // стало: [1, 2, 3, 4]
dq.push_back(5); // стало: [1, 2, 3, 4, 5]
// Доступ по индексу всё ещё O(1), не парься
std::cout << "Элемент под индексом 2: " << dq[2] << 'n'; // Выведет: 3
// Пройтись можно как обычно
for (const auto& elem : dq) {
std::cout << elem << ' ';
}
// Напечатает: 1 2 3 4 5
// Где это применить? Да хоть очередь сделать, или там скользящее окно для какого-нибудь алгоритма.
return 0;
}
А внутри-то как оно, блядь?
Обычно это выглядит как массив указателей на фиксированные куски памяти. Такой себе компромисс: операции с концами — быстро, но вот итерация или доступ по индексу будут чуть медленнее, чем у вектора, потому что нужно ещё вычислить, в каком именно блоке нужный элемент сидит. Но в целом — терпимо, ядрёна вошь.
Так когда его юзать?
Когда тебе нужна очередь (кстати, std::queue по умолчанию на нём и работает), или когда ты постоянно дёргаешь элементы то с начала, то с конца. Главное — не заморачивайся, если тебе критична непрерывная область памяти. Для этого есть вектор, а deque — он для других, гибких дел.
Видео-ответы
▶
▶
▶
▶
▶