Так как мы знакомимся с деком, то нам тяжело понять чем же он хорош, чем лучше других контейнеров. Начнем с общего описания дека. Что этот дек вообще такое в STL? Далеко ходить не будем, возьмем урок физкультуры. Многие из нас знают, что такое «построиться по росту». Так вот, такое построение, что ни на есть самый настоящий дек. Ведь образуется ряд, в этот ряд могут внедряться и с его конца и с его начала и даже занимать позицию внутри этого ряда. А по скорости куда быстрее вставать? Разумеется или в начало или в конец ряда, а в середине ряда нужно искать приблизительно свой рост и потом сравниваться и менять позиции. При этом при вставке в середину ряда, весь ряд будет сдвинут. Вот такая вот аналогия дека из жизни.
Поэтому дек имеет смысл применять тогда когда в приоритете будут вставки или в начало или в конец коллекции, но при этом не исключается, что какие-то элементы придется вставлять и в середину. (соответственно и выбирать из дека аналогично). Хотя деки поддерживают вставку и удаление в средине последовательности, эти операции выполняются за линейное время. Если в приложении должно выполняться много таких операций, лучшим выбором могут оказаться списки.
Интерфейс вектора и дека почти идентичен, различие только в том, что могут отсутствовать некоторые функции, если они отсутствуют, то это значит они не нужны. Так, например класс дека не имеет функций членов capacity, reserve. Просто потому что дек не испытывает необходимости в таком повышении производительности, как в случае векторов.
Используя деки мы должны быть осторожны и не писать кода, который зависит от итераторов или ссылок, остающихся корректными при вставках.
В общем, по сути своей деки те же векторы, следовательно и работать с ними можно как с векторами, просто надо научиться выбирать когда и что выбирать лучше.
Деки оптимизированы для вставки одного элемента либо в начало, либо в конец структуры данных. Такие вставки выполняются за константное время и вызывают копирующий конструктор один раз.
Если элемент вставляется в середину дека, то в наихудшем случае для выполнения этой операции требуется время, линейно зависящее от меньшего значения среди расстояний от точки вставки до начала и до конца дека.
Функции-члены insert, push_front и push_back делают недействительными все итераторы, указывающие в дек. Ссылки также делаются недействительными при вставке в середину дека.
Ну и чтобы был какой-то пример, возьмем простой алгоритм перегруппировки данных в очереди. Перегруппируем все элементы внутри очереди так, чтобы элементы, удовлетворяющие некоторому нашему условию находились перед элементами не удовлетворяющим этому же условию
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#include <iostream> #include <deque> //обязательно если используем deque #include <algorithm> using namespace std; bool mypred(const int x){ return x<51; //наше условие, что элемент в деке меньше чем 51 } int main(){ setlocale(LC_ALL,""); int Arr[]={1,78,89,23,51,49,100}; deque<int> d(&Arr[0],&Arr[7]); cout<<"Исходная\n"; for (deque<int>::iterator it=d.begin();it!=d.end();it++) std::cout<<*it<<" | "; cout<<"\n"; stable_partition(d.begin(),d.end(),mypred); cout<<"\nПолучили\n"; for (deque<int>::iterator it=d.begin();it!=d.end();it++) std::cout<<*it<<" | "; cout<<"\n"; } //Теперь слева все числа меньшие 51, а справа большие или равные |
Может кому непонятно
1 2 3 |
bool mypred(const int x){ return x<51; //Всегда когда x<51 вернет true, иначе false } |
Это тоже самое, что
1 2 3 4 |
bool mypred(const int x){ if (x<51) return true; return false; } |
Вот, собственно, что еще сказать и не знаю. Выбрать дек или вектор во многом зависит от задачи, но, надеюсь этот материал поможет определить имеет ли смысл отдать предпочтение первому или второму.
😛