C++ STL容器那些你不知道的知識點


 

在c++中,容器指的是可以容納各類數據類型的通用數據數據結構,是類模板。 好比set類模板:c++

template <class _Key, class _Compare = less<_Key>,算法

          class _Allocator = allocator<_Key> >編程

class _LIBCPP_TYPE_VIS_ONLY set數組

C++的容器主要分爲三種:順序容器、關聯容器和容器適配器。數據結構

而訪問容器元素咱們須要迭代器(引入容器頭文件就能夠了,不須要單獨由於頭文件),迭代器有如下幾個屬性:less

1.用於指向順序容器和關聯容器的元素編程語言

2.用法和指針相似函數

3.有const(容器類名::iterator 變量名)和非const兩種(容器類名::const_iterator 變量名)性能

4.經過迭代器能夠讀取它指向的元素學習

5.非const迭代器和能夠修改其指向的元素

順序容器

何爲順序容器,也就是說元素的位置是順序插入的,插入位置與元素的值無關,核心是容器沒有排序。 順序容器都具備如下10個成員函數:

#返回迭代器

begin

end

rbegin  //返回指向最後一個元素的迭代器

rend

#返回元素引用

front

back

#其餘

erase(刪除區間時返回被刪除元素後面的迭代器;也可刪除一個或幾個元素)

clear

push_back

pop_back

順序容器有如下三種:

1.vector動態數組 頭文件<vetor>

元素在內存中是連續存放的。

隨機存取時間:常數時間(由於能夠經過下標直接訪問到地址)。

在尾部增刪元素一般是常數時間(正常是常數時間,若是超出了默認分配的元素個數,會從新分配存儲空間,此時會消耗更多時間)。

在中間或者頭部增刪元素:o(n)(會移動其餘元素的位置)。

迭代器類型:隨機訪問(支持下標訪問、隨機移動,例:a[i])。

查詢時間:o(n)(由於沒有排序,只能現行查找,效率較低)。

可見vector在中間或者頭部增刪元素性能較低。

優勢:內存和C徹底兼容、高效隨機訪問、節省空間

缺點:內部插入刪除元素代價巨大、動態大小查過自身容量須要申請大量內存作大量拷貝。

構造函數:

vector();

vector(int n);

vector(int n, const T &a); //把n個元素初始化爲a

vector(iterator first,iterator last); //初始化爲其餘容器上區間[first,last)一致的內容

經常使用成員函數

void pop_back();

void push_back(const T &val);

int size();

T & font();

T & back();

deque[讀:dek,以前常常讀dkju:]雙向隊列 頭文件<deque>

元素在內存中連續存放(連續內存的容器有個明顯的缺點,就是有新元素插入或老元素刪除的時候,爲了給新元素騰出位置或者填充老元素的空缺,同一塊內存中的其餘數據須要進行總體的移位,這種移位的拷貝代價有時是很是巨大的。deque其實是分配到不一樣內存塊,經過鏈表把內存塊連在一塊兒,再進行連續存放,是list與vector的折中)。

隨機存取時間:常數時間(僅次於vector,由於有可能存在尾部的內存位置在頭部以前的場景)。

在兩端增刪元素一般是常數時間。(deque不像vector沒有容量,不須要從新分配內存空間。這是由於deque由動態分配的連續空間,即緩衝區,組合而成,隨時能夠增長一段新的空間連接起來。它沒有必要像vector那樣「因舊空間不足而從新分配2倍的空間,而後複製元素,再釋放舊空間」。當從新分配緩衝區時,耗時增長)。

在中間插入:時間複雜度較高。

迭代器類型:隨機訪問(效率低於vector)。

查詢時間:o(n)(緣由同上)。

優勢:高效隨機訪問、內部插入刪除元素效率方便、兩端push、pop效率很高 。

缺點:內存佔用比較高 。


 

list雙向鏈表 頭文件<list>

元素在內存中不連續分配(由於指針能夠獲取先後元素的地址),因此不支持隨機存取。

在任何位置增刪元素時間:常數時間。

查詢時間:o(n)(緣由同上)。

迭代器類型:雙向(不支持下標訪問,不支持迭代器的比較運算符,和+-運算符)

優勢:任意位置插入刪除元素常量時間複雜度、兩個容器融合是常量時間複雜度

缺點:不支持隨機訪問、比vector佔用更多的存儲空間

經常使用成員函數:(注意這些在順序容器中都是list獨有的)

push_front

pop_front

sort  //不支持STLsort算法

remove

unique

merge

reverse

splice

特別說明,list的sort函數有無參和compare兩個版本

list<T> classname

classname.sort(compare);  //compare自定義

classname.sort();

關聯容器(迭代器類型:雙向)

關聯的意思就是元素是排序的。

插入與檢索元素時間: o(log(N))(由於經過紅黑二叉樹實現,時間與平衡二叉樹一致)。

須要注意的是,STL中有些算法好比sort,binary_search須要經過隨機訪問迭代器訪問容器中的元素,所以list以及關聯容器就不能支持該算法!

主要包括如下4種:

set

multiset

map

multimap

除了個容器都有的成員函數外,它們都有如下成員函數

find

lower_bound

upper_bound

equal_range

count

insert

map與set的不一樣點在於,map中存放的元素有且僅有兩個成員變量,first(相似於key),second(相似於value),map能夠根據first對元素排序和檢索。

set與multiset的不一樣在於,後者容許存在相同值的元素。 map與multimap的不一樣在於,後者容許存在相同的first值的元素。

容器適配器(不支持迭代器)

這個概念聽起來有點抽象,其實就是STL幫咱們抽象了實際工做中所須要的數據操做方式。舉個栗子,交流電能夠有任意的傳輸電壓,可是實際生活中咱們只須要220v就夠了,變壓器幫咱們實現了這個基本的功能。同理,容器的操做方式多種多樣,可是其實咱們只須要他們按照實際的一些規範來操做便可。

他們都有如下3個成員函數:

push

top

pop

STL中的排序,查找,變序算法都不適合容器適配器(由於容器適配器的元素位置不可隨意改變,而且訪問有必定的訪問規則,不支持隨機訪問)。

stack 棧 頭文件<stack>

是一個有限序列,並知足序列中被刪除、檢索和修改的項只能是最近插入序列的項(棧頂項)。也即,先進先出LIFO。

能夠用vector,deque,list(性能最差)實現,編譯器缺省是用deque實現的。

好比,在程序調試中,錯誤堆棧就是一種應用。

queue 隊列 頭文件 <queue>

插入只能夠在尾部進行,刪除、檢索和修改只容許從頭部進行。先進先出FIFO。

queue因爲pop,push發生在對頭,因此不能用vector實現,能夠用list,deque實現,編譯器缺省用deque實現。

好比,應用於須要保證消息順序性的場景,如消息隊列。

priority_queue 優先級隊列 頭文件<queue>

最高優先級元素老是第一個出列。

它需採用堆排序來保證元素老是在最前面,所以要求隨機訪問,因此不能使用list實現,能夠用vector和deque實現,編譯器缺省狀況下用vector實現。

好比,操做系統的線程的調度算法,有的是按照優先級來調度的。

總結


 

1.若是須要隨機訪問,用vector;

2.若是存儲元素的數目已知,用vector;

3.須要任意位置隨機插入刪除,用list;

4.常常在容器的首部尾部插入刪除元素,用deque;

5.元素結構複雜用list,也能夠用vector存儲指針(須要額外的精力去維護內存),看需求;

6.若是操做是基於鍵值,用set/map;

7.若是須要常常的搜索,用map/set。

C語言就是一個既能夠強化思惟能力,又能夠打好編程基礎的編程語言,對這個感興趣的同窗來小編這裏學學吧。即便是零基礎的學習者,均可以一塊兒成長進步。

相關文章
相關標籤/搜索