C++ STL容器底層數(shù)據(jù)結(jié)構(gòu)總結(jié)

STL 就是所謂的標(biāo)準(zhǔn)模板庫(kù)(Standard Template Library),這可能是C++程序員的一大利器。

總的來說,STL包括幾個(gè)部分:容器,算法(泛型算法),迭代器三個(gè)主要部分(當(dāng)然還包含仿函數(shù),適配器等其他部分),下圖說明了三個(gè)主要部分之間的關(guān)系(網(wǎng)圖,侵刪)。

STL三個(gè)主要部分的關(guān)系示意圖

要是詳細(xì)的總結(jié),這肯定是一本類似于《C++ Primer》的大書。本篇文章主要是對(duì)于STL中的常用容器的底層數(shù)據(jù)結(jié)構(gòu)進(jìn)行總結(jié)整理。

I、vector

1.1 vector底層數(shù)據(jù)結(jié)構(gòu)

vector是我們用到最多的數(shù)據(jù)結(jié)構(gòu),其底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組,由于數(shù)組的特點(diǎn),vector也具有以下特性:
1、O(1)時(shí)間的快速訪問;
2、順序存儲(chǔ),所以插入到非尾結(jié)點(diǎn)位置所需時(shí)間復(fù)雜度為O(n),刪除也一樣;
3、擴(kuò)容規(guī)則:
當(dāng)我們新建一個(gè)vector的時(shí)候,會(huì)首先分配給他一片連續(xù)的內(nèi)存空間,如std::vector<int> vec,當(dāng)通過push_back向其中增加元素時(shí),如果初始分配空間已滿,就會(huì)引起vector擴(kuò)容,其擴(kuò)容規(guī)則在gcc下以2倍方式完成:
首先重新申請(qǐng)一個(gè)2倍大的內(nèi)存空間;
然后將原空間的內(nèi)容拷貝過來;
最后將原空間內(nèi)容進(jìn)行釋放,將內(nèi)存交還給操作系統(tǒng);

測(cè)試代碼如下:

#include<iostream>
#include<vector>
using namespace std;

void mycapacity(const vector<int>& vec)
{
    cout << "分配總空間大小為:" << vec.capacity() << endl;
}

void mysize(const vector<int>& vec)
{
    cout << "已用空間大小為:" << vec.size() << endl;
}

void myprint(const vector<int>& vec)
{
    for (int i = 0; i < vec.size(); ++i)
        cout << vec[i] << ",";
    cout << endl;
}


int main()
{
    vector<int> vec;
    cout << "起始狀態(tài):" << endl;
    mycapacity(vec);
    mysize(vec);
    cout << "========================" << endl;

    for (int i = 0; i < 10; ++i) {
        vec.push_back(i);
        cout << "壓入第" << i+1 << "個(gè)元素之后:" << endl;
        myprint(vec);
        mycapacity(vec);
        mysize(vec);
        cout << "========================" << endl;
    }

    return 0;
}
測(cè)試輸出結(jié)果

從輸出結(jié)果中的三個(gè)紅色箭頭可以看出vector的擴(kuò)容規(guī)則。

4、注意事項(xiàng):
根據(jù)vector的插入和刪除特性,以及擴(kuò)容規(guī)則,我們?cè)谑褂胿ector的時(shí)候要注意,在插入位置和刪除位置之后的所有迭代器和指針引用都會(huì)失效,同理,擴(kuò)容之后的所有迭代器指針和引用也都會(huì)失效。

II、map & multimap & unordered_map & unordered_multimap

2.1 map與multimap底層數(shù)據(jù)結(jié)構(gòu)

map與multimap是STL中的關(guān)聯(lián)容器、提供一對(duì)一key-value的數(shù)據(jù)處理能力; map與multimap的區(qū)別在于,multimap允許關(guān)鍵字重復(fù),而map不允許重復(fù)。

這兩個(gè)關(guān)聯(lián)容器的底層數(shù)據(jù)結(jié)構(gòu)均為紅黑樹,關(guān)于紅黑樹的理解可以參考教你透徹了解紅黑樹一文。

根據(jù)紅黑樹的原理,map與multimap可以實(shí)現(xiàn)O(lgn)的查找,插入和刪除。

2.2 unordered_map 與unordered_multimap底層數(shù)據(jù)結(jié)構(gòu)

unordered_map與unordered_multimap 對(duì)比2.1中的兩種map在于其2.1中的兩個(gè)容器實(shí)現(xiàn)了以key為序排列,也就是說map與multimap為有序的。

而unordered_map與unordered_multimap中key為無序排列,其底層實(shí)現(xiàn)為hash table,因此其查找時(shí)間復(fù)雜度理論上達(dá)到了O(n),之所以說理論上是因?yàn)樵诶硐霟o碰撞的情況下,而真實(shí)情況未必如此。

III、set & multiset & unordered_set & unordered_multiset

以上四種容器也都是關(guān)聯(lián)容器,set系與map系的區(qū)別在于map中存儲(chǔ)的是<key-value>,而set可以理解為關(guān)鍵字即值,即只保存關(guān)鍵字的容器。

3.1 set & multiset底層數(shù)據(jù)結(jié)構(gòu)

set與multiset有序存儲(chǔ)元素,這兩種容器的底層實(shí)現(xiàn)與map一樣都是紅黑樹,所以能實(shí)現(xiàn)O(lgn)的查找,插入,刪除操作。

set與multiset的區(qū)別在于是否允許重復(fù);

3.2 unordered_set & unordered_multiset

與unordered_map & unordered_multimap相同,其底層實(shí)現(xiàn)為hash table;

IV、 priority_queue

4.1 priority_queue

優(yōu)先級(jí)隊(duì)列相當(dāng)于一個(gè)有權(quán)值的單向隊(duì)列queue,在這個(gè)隊(duì)列中,所有元素是按照優(yōu)先級(jí)排列的。

priority_queue根據(jù)的處理規(guī)則來調(diào)整元素之間的位置,關(guān)于堆的原理,可以參考;

根據(jù)堆的特性,優(yōu)先級(jí)隊(duì)列實(shí)現(xiàn)了取出最大最小元素時(shí)間復(fù)雜度為O(1),對(duì)于插入和刪除,其最壞情況為O(lgn)。

V、 其他數(shù)據(jù)結(jié)構(gòu)

list的底層數(shù)據(jù)結(jié)構(gòu)為雙向鏈表,特點(diǎn)是支持快速的增刪。
queue為單向隊(duì)列,為先入先出原則。
deque為雙向隊(duì)列,其對(duì)比queue可以實(shí)現(xiàn)在頭尾兩端高效的插入和刪除操作。

歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處wenmingxing 你好呀 C++

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容