STL容器的常用方法

以下內容如有錯誤,歡迎指出。

STL容器都是以類模板的形式實現的,所以在使用之前必須用類型進行實例化爲具體的模板類

vector

以int類型實例化

vector<int> vec1;//構造空的vector
vector<int> vec2(10);//構造大小爲10,值按照默認初始化規則默認初始化
vector<int> vec3(10, 1);//構造大小爲10,初始值爲1
vector<int> vec4(vec2);//通過拷貝vec2來構造
vector<int> vec5(vec3.begin(), vec3.end);//用[First,last)之間的元素來構造

vec1=vec2;//賦值操作
vec1.size();//返回vec1的大小,這裏爲10
vec1.empty();//判斷vec1是否爲空,爲空返回true,否則返回false
vec1.at(n);//返回vec1中的第n個元素的引用,會判斷是否越界
vec1[n];//返回vec1中的第n個元素的引用,不會判斷是否越界
vec1.front();//返回vec1中的頭元素的引用
vec1.back();//返回vec1中的最後一個元素的引用
vec1.push_back(1);//在vec1的最後插入值爲1的元素,可能會引起空間從新分配
vec1.pop_back();//刪除vec1的最後一個元素

注意:vector沒有pop_front和push_front操作

vector<int>::iterator it1=vec1.begin();//返回頭迭代器
vector<int>::iterator it2=vec1.end();//返回尾後迭代器
vector<int>::iterator it3=vec1.rbegin();//返回尾後迭代器
vector<int>::iterator it4=vec1.rend();//返回頭迭代器

注意:插入操作都是在position(哨兵迭代器)之前插入

vector<int>::iterator it=vec1.insert(2,4);//在vec1第三個元素之前插入值爲4的元素,返回插入元素的迭代器
vec1.insert(2,3,4);//在vec1的第三個元素之前插入3個值爲4的元素,返回void
vec1.insert(2,vec3.begin(),vec3.end());//在vec1的第3個元素之前插入[First,last)
vec1.assign(vec3.begin(),vec3.begin()+5);//將vec3的前5個元素賦值給vec1前5個元素
vec1.erase(1);//刪除vec1的第2個元素,其實真實操作是把後面的元素依次向前複製
vec1.erase(vec1.begin(),vec.begin()+2);//刪除迭代器範圍內的元素
vec1.clear();//刪除所有元素

vec1.swap(vec2);//交換兩個vector
vec1.reserve(20);//重新分配大小爲20
vec1.capacity();//返回當前分配的存儲空間的長度(這個可能比實際需求的空間大)

注意:

  • vector分配的空間是連續的
  • vector插入元素,如果不引起空間重新分配,會使插入位置以後的迭代器全部失效。如果引起空間重新分配,所有迭代器都會失效。
  • 刪除元素,會使當前位置及後面的所有迭代器失效。
  • vector的迭代器是Random Access itreator,可以說是類似一般指針,在侯捷的《STL的源碼剖析》中typedef value_type* iterator。而在VS中就是類似一般指針,由於屬於派生類,sizeof大小爲12。但是總體來說都支持一般指針的所有操作。

list

以int類型實例化

list<int> l1;//構造一個空list
list<int> l2(10,1);//構造大小爲10,元素值爲1
list<int> l3(l2);//通過拷貝l2來構造
list<int> l4(l3.begin(), l3.begin()+5);//用[first,last)來構造


l1=l2;//賦值操作
l2.resize(20);//將l2的大小變爲20,在以前list尾節點後面追加int()元素,若大小比以前小直接從後刪除多餘的節點
l2.resize(25,2);//將l2大小變爲25,增加的元素的值爲2,若大小比以前小直接從後刪除多餘的節點
l1.size();//返回l1的大小
l1.empty();//判斷是否爲空,爲空,返回true;否則返回false


l1.front();//返回第一個元素的引用
l1.back();//返回最後一個元素的引用
l1.push_front(5);//在第一個位置之前插入一個值爲5元素,返回void
l1.pop_front();//刪除第一個元素,返回void
l1.push_back(5);//插入一個值爲5的元素到最後,返回void
l1.pop_back();//刪除最後一個元素,返回void


list<int>::iterator it1;
it1=l1.begin();//返回起始迭代器,頭的下一個,list源碼實現中head是一個空節點
l1.end();//返回尾後迭代器
l1.rbegin();//返回尾後迭代器
l1.rend();//返回頭迭代器


l2.insert(l2.end(), 2);//在l2的尾端插入一個值爲2的元素,返回指向插入元素的迭代器
l2.insert(l2.begin(), 4, 3);//在l2的起始位置插入4個值爲3的元素,返回void
l2.insert(l2.begin(), l1.begin(), l1.end());//在l2的起始位置插入l1的區間[first,last),返回void
l2.assign(l1.begin(), l1.begin()+3);//用[first,last)重新給l2賦值,先刪除l2的所有元素再插入
l2.assign(5,4);//先刪除l2的所有元素再插入5個值爲4的元素
l2.erase(l2.begin());//刪除l2的第一個元素,返回下一個迭代器
l2.erase(l2.begin(), l2.begin()+2);//刪除[first,last)區間元素,返回指向刪除區間的下一個元素的迭代器
l2.clear();//刪除所有元素
l1.remove(5);//刪除所有元素之等於5的節點,返回void
l1.remove_if(predicate);//刪除所有讓一元謂詞爲true的元素
l1.unique();//刪除每一個和前一個元素相同的元素


l3.sort();//用<操作排序
l4.sort(predicate);//用滿足謂詞的順序排序
l3.merge(l4);//合併l4到l3(要求兩個鏈表都爲有序隊列,按遞增排序)
l1.swap(l3);//交換l1和l3,返回void
l1.splice(l1.begin()+1, l3);//將l3拼接在l1.begin()+1之後,返回void
l1.splice(l1.begin(), l4, l4.begin());//將l4.begin()所指節點拼接到l1的第一個節點之後,返回void
l1.splice(l1.begin(), l5.begin(), l5.end());//將[first,last)拼接到l1的第一個節點之後,返回void
l1.reverse();//倒置鏈表

list的迭代器型別是Bidirectional iterator

list<int>::iterator it=l1.begin();//list的迭代器支持以下操作
operator*();
operator->();
operator++();//前自加
operator++(int);//後自加
operator--();
operator--(int);
operator==();
operator!=();

注意

  • list分配的空間是非連續空間
  • list巧妙的實現爲一個環狀鏈表,鏈表的head爲一個空節點
  • list的插入操作不會造成迭代器失效,刪除操作只會使指向被刪除元素的迭代器失效

deque(雙端隊列)

以int類型實例化

deque<int> deq1;//構造一個空deque
deque<int> deq2(10);//構造大小爲10的deque,值爲int()
deque<int> deq3(10,4);//大小爲10,值爲4
deque<int> deq4(deq3);//拷貝構造
deque<int> deq5(deq4.begin(), deq4.end());//拷貝[first,last)來構造


deq1=deq2;//賦值
deq1.begin();//返回頭迭代器
deq1.end();//返回尾後迭代器
deq1.rbegin();//返回尾後迭代器
deq1.rend();//返回頭迭代器


deq1.resize(15);//重新分配大小,並在後面填補值爲int()的元素
deq1.resize(20,4);//重新分配大小,並在後面填補值爲4的元素
deq1.size();//返回隊列大小
deq1.empty();//判斷隊列是否爲空,爲空返回true,否則返回false


deq1.at(5);//返回位置爲5的元素的引用,以0爲基準
deq1[5];//返回位置爲5的元素的引用,以0爲基準
deq1.front();//返回第一個元素的引用
deq1.back();//返回最後一個元素的引用
deq1.push_front(4);//在隊列頭的位置插入一個值爲4的元素
deq1.pop_front();//刪除隊列的第一個元素
deq1.push_back(4);//在隊列的最後
deq1.pop_back();//刪除隊列的最後一個元素


deq2.assign(deq1.begin(), deq1.begin()+10);//用[first,last)來賦值,先刪除所有元素
deq2.assign(10,3);//先刪除所有元素,再分配10個大小,值爲3
deq2.insert(deq2.begin(), 7);//在隊列頭插入值爲7的元素
deq2.insert(deq2.begin(), 3, 7);//在隊列頭插入3個值爲7的元素
deq2.insert(deq2.begin(), deq1.begin(),deq1.begin()+4);//插入[first,last)
deq2.erase(deq2.begin());//刪除迭代器所指元素
deq2.erase(deq2.begin(),deq2.begin()+3);//刪除[first,last)區間元素
deq2.clear();//刪除所有元素
deq3.swap(deq1);//交換兩個隊列

deque的迭代器型別是Random Access iterator

deque<int>::iterator it=deq1.begin();//deque的迭代器支持以下操作
operator*();
operator->();
operator++();//前自加
operator++(int);//後自加
operator--();
operator--(int);
operator+();
operator+=();
operator-();
operator-=();
operator[]();
operator==();
operator!=();
operator>();
operator<();
operator>=();
operator<=();

注意

  • deque分配的空間是分段定量連續空間,爲了維持整體連續的假象,採用一塊map(一小塊連續空間),其中每個元素(node)都是指針,指向另一段較大的連續線性空間,稱爲緩衝區,這纔是存儲空間主體。
  • deque的迭代器型別是Random Access iterator,實現起來比vector的迭代器複雜。
  • deque插入元素到首尾時,會使首尾迭代器失效,但是指向元素的引用和指針不會失效,插入到除首尾之外的其他位置會導致迭代器、引用和指針失效。刪除首尾元素,會使首尾迭代器失效,刪除首尾之外的其他位置的元素會導致迭代器、引用和指針失效。

queue(先進先出,底端進頂端出)

queue的默認底層實現容器是deque

以int類型實例化

queue<int> que1;//構造空的queue
queue<int> que2(deque<int>(5,3));//deque容器來構造

que1.empty();//判斷是否爲空,爲空返回true,否則返回false
que1.size();//返回隊列大小
que1.front();//返回隊列的第一個元素的引用
que1.back();//返回隊列最後一個元素的引用
que1.push(1);//從底端插入
que1.pop();//從頂端刪除,返回void

注意:queue只能從頭尾訪問元素,不提供迭代器,不能遍歷。

priority_queue(優先隊列)

默認底層實現容器爲vector,默認用最大堆(max-heap)完成優先

以int類型實例化

priority_queue<int> prique1;//構造空的優先隊列
priority_queque<int> prique2(vec1.begin(), vec1.end());//用一個vector的[first,last)區間來構造

prique2.empty();//判斷隊列是否爲空
prique2.size();//
prique2.top();//返回最高優先級元素的引用
prique2.push(1);//插入值爲1的元素,會進行堆排序
prique2.pop();//刪除最高優先級元素

注意:priority_queue只有頂端元素才能被外界取用,不提供迭代器,不提供遍歷


stack(先進後出,頂端出入)

默認底層實現容器deque

以int類型實例化

stack<int> sta1;//構造一個空的stack
stack<int> sta2(deque<int>(5,3));//用deque容器構造

sta2.empty();
sta2.size();
sta2.top();//返回頂端元素的引用
sta2.push(1);//從頂端插入值爲1的元素
sta2.pop();//從頂端刪除元素

注意:stack是先進先出的數據結構,只能從頂端存取元素,不提供迭代器,不提供遍歷


map

map的實現分兩種:繼承rb_tree實現、組合rb_tree實現

  • 底層以RB_tree(紅黑樹)實現key排序,每個節點的值叫value_type。默認用了less<key_type>模板函數作爲key_compare。
  • map要注意區分key_type,value_type,mapped_type。其中value_type=pair<cosnt key_type, mapped_type>
  • map的模板聲明:
    template<class _Kty,//鍵值類型
    class _Ty,//映射值類型
    class _Pr = less<_Kty>,//鍵值比較仿函數類型,默認less
    class _Alloc = allocator<pair<const _Kty, _Ty> > >//配置器類型
    class map;
map<string, int> students1;//構造一個空的map
map<string, int> students2;//

注意:用insert向map中插入元素時,採用的底層機制rb_tree的insert_unique()實現。如果已經有鍵相等的元素則插入失敗,返回一個pair

students1["xiaoming"]=9;//相當於查找或插入xiaoming,對返回的mapped引用賦值
students1.insert(pair<string,int>("xiaohong",10));//插入一個pair
students1.insert(make_pair("xiaozhang",11));//插入一個pair
students1.insert(map<string,int>::value_type("xiaoli,10"));

students2=students1;//賦值運算
map<string,int>::iterator it=students2.begin();//返回map的第一個迭代器
students1.end();//返回map的尾後迭代器

students2.erase(it);//刪除it迭代器所指的元素,返回指向下一個元素的迭代器
students2.erase("xiaoli");//刪除students2中鍵值和“xiaoli”相同的元素,返回刪除的所有匹配元素的個數
students2.erase(students2.begin(),students2.begin()+1);刪除[first,last)區間元素
students2.clear();//刪除所有元素

students1.size();//返回map容器的大小
students1.empty();//判斷map容器是否爲空
students1.find("xiaoming");//返回指向配置鍵值元素的迭代器,如果沒有找到就返回尾後迭代器
students1.count("xiaoming");//返回所有鍵值匹配元素的個數
students1.lower_bound("xiaoming");//返回指向最左端不小於這個鍵值的元素的迭代器(這裏的例子不合適用這個方法,單單說明這個方法的用法)
students1.upper_bound("xiaoming");//返回指向最左端大於這個鍵值的元素的迭代器
students1.swap(students2);//交換兩個map

map的迭代器型別是bidirectional iterator,自增自減都是通過rb_tree的迭代器的內部函數實現的

map的迭代器支持以下主要操作
operator*();
operator->();
operator++();//前自加
operator++(int);//後自加
operator--();
operator--(int);
operator==();
operator!=();

注意

  • map分配的節點空間是非連續空間。每個節點也就是紅黑樹的節點,包括left,right,parent,color,value_type成員變量。
  • map的迭代器型別是bidirectional access iterator,實現起來比list的迭代器複雜。
  • map插入操作不會造成迭代器失效,刪除操作只會使指向被刪除元素的迭代器失效。
  • operator[]操作,先查找map中是否有相同鍵值,如果有就返回mapped_type的引用,如果沒有就插入mapped_type(),也就是默認值,然後返回mapped_type的引用。

set

set的實現和map一樣也分兩種:繼承rb_tree實現、組合rb_tree實現

  • 底層以RB_tree(紅黑樹)實現key排序,只有鍵值,key_type和value_type是一樣的。默認用了less<key_type>模板函數作爲key_compare。
  • set的模板聲明:
    template<class _Kty,//健
    class _Pr = less<_Kty>,//用於排序比較仿函數
    class _Alloc = allocator<_Kty> >
    class set;
int array[5]={0,1,2,3,4};
set<int> orderset1(array,array+5);//用[first,last)構造一個set
set<int> orderset2;//構造一個空的set

注意:用insert向set中插入元素時,採用的底層機制rb_tree的insert_unique()實現。如果已經有鍵相等的元素則插入失敗,返回一個pair

orderset1.insert(10);//插入一個鍵值爲10的元素
orderset2=orderset1;//賦值運算
set<int>::iterator it=orderset1.begin();//返回set的第一個迭代器
orderset1.end();//返回set的尾後迭代器

orderset1.erase(it);//刪除it迭代器所指的元素,返回指向下一個元素的迭代器
orderset1.erase(0);//刪除orderset1中鍵值爲0相同的元素,返回刪除的所有匹配元素的個數
orderset1.erase(orderset1.begin(),orderset1.begin()+1);刪除[first,last)區間元素
orderset1.clear();//刪除所有元素

orderset2.size();//返回set容器的大小
orderset2.empty();//判斷set容器是否爲空
orderset2.find(4);//返回指向鍵值爲4的元素的迭代器,如果沒有找到就返回尾後迭代器
orderset2.count(2);//返回所有鍵值匹配元素的個數
orderset2.lower_bound(3);//返回指向最左端不小於這個鍵值的元素的迭代器
orderset2.upper_bound(4);//返回指向最左端大於這個鍵值的元素的迭代器
orderset2.swap(orderset1);//交換兩個set

set的迭代器型別是bidirectional iterator,自增自減都是通過rb_tree的迭代器的內部函數實現的

set的迭代器支持以下主要操作
operator*();
operator->();
operator++();//前自加
operator++(int);//後自加
operator--();
operator--(int);
operator==();
operator!=();

注意

  • set分配的節點空間是非連續空間。每個節點也就是紅黑樹的節點,包括left,right,parent,color,value_type成員變量。
  • set的迭代器型別是bidirectional access iterator,實現起來比list的迭代器複雜。
  • set插入操作不會造成迭代器失效,刪除操作只會使指向被刪除元素的迭代器失效。

multimap

multimap的特性和用法與map基本相同,差別在於它允許鍵值重複,因此它的插入操作採用的底層機制rb_tree的insert_equal()而非insert_unique()。還有就是multimap不支持operator[]操作。


multiset

multiset的特性和用法與set完全相同,唯一的差別在於它允許鍵值重複,因此它的插入操作採用的底層機制rb_tree的insert_equal()而非insert_unique()。

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