STL容器:deque的簡介與使用

deque的原理介紹

deque(雙端隊列):是一種雙開口的"連續"空間的數據結構,雙開口的含義是:可以在頭尾兩端進行插入和刪除操作,且時間複雜度爲O(1),與vector比較,頭插效率高,不需要搬移元素;與list比較,空間利用率比較高。
在這裏插入圖片描述
deque並不是真正連續的空間,而是由一段段連續的小空間拼接而成的,實際deque類似於一個動態的二維數組,其底層結構如下圖所示:
在這裏插入圖片描述
雙端隊列底層是一段假象的連續空間,實際是分段連續的,爲了維護其“整體連續”以及隨機訪問的假象,落在了deque的迭代器身上,因此deque的迭代器設計就比較複雜,如下圖所示:
在這裏插入圖片描述
那deque是如何藉助其迭代器維護其假想連續的結構呢?
在這裏插入圖片描述

deque的缺陷

  • 與vector比較,deque的優勢是:頭部插入和刪除時,不需要搬移元素,效率特別高,而且在擴容時,也不需要搬移大量的元素,因此其效率是必vector高的。
  • 與list比較,其底層是連續空間,空間利用率比較高,不需要存儲額外字段。

但是,deque有一個致命缺陷:不適合遍歷,因爲在遍歷時,deque的迭代器要頻繁的去檢測其是否移動到某段小空間的邊界,導致效率低下,而序列式場景中,可能需要經常遍歷,因此在實際中,需要線性結構時,大多數情況下優先考慮vector和list,deque的應用並不多,而目前能看到的一個應用就是,STL用其作爲stack和queue的底層數據結構。

如下代碼對比了大量數據快排時,vector的效率遠遠高於queue的效率
隨機訪問才能很好的支持排序,而恰恰queue的隨機訪問效率很低

#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>
#include <ctime>
using namespace std;

int main()
{
    vector<int> v;
    deque<int> d;
    const int n = 1000000;
    srand((unsigned int)time(0));
    for (int i = 0; i < n; ++i)
    {
        int val = rand();
        v.push_back(val);
        d.push_back(val);
    }

    int begin1 = clock();
    sort(v.begin(), v.end());
    int end1 = clock();

    int begin2 = clock();
    sort(d.begin(), d.end());
    int end2 = clock();

    cout << end1 - begin1 << endl;
    cout << end2 - begin2 << endl;
    return 0;
}

在這裏插入圖片描述
爲什麼選擇deque作爲stack和queue的底層默認容器?
stack是一種後進先出的特殊線性數據結構,因此只要具有push_back()和pop_back()操作的線性結構,都可以作爲stack的底層容器,比如vector和list都可以;queue是先進先出的特殊線性數據結構,只要具有push_back和pop_front操作的線性結構,都可以作爲queue的底層容器,比如list。但是STL中對stack和queue默認選擇deque作爲其底層容器,主要是因爲:

  1. stack和queue不需要遍歷(因此stack和queue沒有迭代器),只需要在固定的一端或者兩端進行操作。
  2. 在stack中元素增長時,deque比vector的效率高(擴容時不需要搬移大量數據);queue中的元素增長
    時,deque不僅效率高,而且內存使用率高。

結合了deque的優點,而完美的避開了其缺陷。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章