STL的一個重要特點是數據結構和算法的分離
盡管這是個簡單的概念,但這種分離確實使得STL變得非常通用。例如,由于STL的sort()函數是完全通用的,你可以用它來操作幾乎任何數據集合,包括鏈表,容器和數組
STL另一個重要特性是它不是面向對象的
為了具有足夠通用性,STL主要依賴于模板而不是封裝,繼承和多態(虛函數)——OOP的三個要素。你在STL中找不到任何明顯的類繼承關系。這好像是一種倒退,但這正好是使得STL的組件具有廣泛通用性的底層特征。另外,由于STL是基于模板,內聯函數的使用使得生成的代碼短小高效
(重要知識點(10種):
序列式容器:(3種)vector、deque、list
關聯式容器:(4種)set、multiset、map、multimap
順序容器適配器:(3種)queue、priority_queue、stack)
STL中六大組件:
容器,迭代器,算法,仿函數,適配器,分配器
容器
STL中的容器有序列式容器,關聯式容器,容器適配器,位集和串包等
容器類自動申請和釋放內存,無需new和delete操作
(1)序列式容器:每個元素都有固定位置——取決于插入時機和地點,和元素值無關,vector、deque、list
vector(單向動態數組):將元素置于一個動態數組中加以管理,可以隨機存取元素(用索引直接存取),數組尾部添加或移除元素非??焖佟5窃谥胁炕蝾^部安插元素比較費時;
deque(雙向動態數組):是“double-ended queue”的縮寫,可以隨機存取元素(用索引直接存取),數組頭部和尾部添加或移除元素都非??焖?。但是在中部或頭部安插元素比較費時;
list(雙向鏈表):不提供隨機存?。ò错樞蜃叩叫璐嫒〉脑兀?,在任何位置上執行插入或刪除動作都非常迅速,內部只需調整一下指針;
(2)關聯式容器:元素位置取決于特定的排序準則,和插入順序無關,set、multiset、map、multimap
set/multiset:set內的相同數值的元素只能出現一次,multisets內可包含多個數值相同的元素,內部的元素依據其值自動排序,由二叉樹實現,便于查找;
map/multimap:map的元素是成對的鍵值/實值,map內的相同數值的元素只能出現一次,multimaps內可包含多個數值相同的元素,內部的元素依據其值自動排序,由二叉樹實現,便于查找;
迭代器
Iterator(迭代器):用于提供一種方法順序訪問一個聚合對象中各個元素, 而又不需暴露該對象的內部表示。或者這樣說可能更容易理解:Iterator模式是運用于聚合對象的一種模式,通過運用該模式,使得我們可以在不知道對象內部表示的情況下,按照一定順序(由iterator提供的方法)訪問聚合對象中的各個元素
迭代器的作用:能夠讓迭代器與算法不干擾的相互發展,最后又能無間隙的粘合起來,重載了*,++,==,!=,=運算符。用以操作復雜的數據結構,容器提供迭代器,算法使用迭代器;常見的一些迭代器類型:iterator、const_iterator、reverse_iterator和const_reverse_iterator
算法
算法部分主要由頭文件<algorithm>,<numeric>和<functional>組成。
<algorithm>是所有STL頭文件中最大的一個(盡管它很好理解),它是由一大堆模版函數組成的,可以認為每個函數在很大程度上都是獨立的,其中常用到的功能范圍涉及到比較、交換、查找、遍歷操作、復制、修改、移除、反轉、排序、合并等等。
<numeric>體積很小,只包括幾個在序列上面進行簡單數學運算的模板函數,包括加法和乘法在序列上的一些操作。
<functional>中則定義了一些模板類,用以聲明函數對象。
STL中算法大致分為四類:
非可變序列算法:指不直接修改其所操作的容器內容的算法。
可變序列算法:指可以修改它們所操作的容器內容的算法。
排序算法:對序列進行排序和合并的算法、搜索算法以及有序序列上的集合操作。
數值算法:對容器內容進行數值計算。
適配器
標準庫提供了三種順序容器適配器:queue(FIFO隊列)、priority_queue(優先級隊列)、stack(棧)
要使用適配器,需要加入一下頭文件:
#include <stack> //stack
#include <queue> //queue、priority_queue
queue
默認順序容器:deque
可用順序容器:list、deque
說明:FIFO隊列,基礎容器必須提供push_front()運算
priority_queue
默認順序容器:vector
可用順序容器:vector、deque
說明:優先級隊列,基礎容器必須提供隨機訪問功能
stack
默認順序容器:deque
可用順序容器:vector、list、deque
說明:棧
定義適配器
1、初始化:stack<int> stk(dep);
2、覆蓋默認容器類型:stack<int,vector<int> > stk;
范例函數
queue/priority_queue范例函數:
queue<int> q;
priority_queue<int> q;
兩者通用函數:
q.empty(); //判斷隊列是否為空
q.size(); //返回隊列長度
q.push(item); //對于queue,在隊尾壓入一個新元素;對于priority_queue,在基于優先級的適當位置插入新元素
queue only:
q.front(); //返回隊首元素的值,但不刪除該元素
q.back(); //返回隊尾元素的值,但不刪除該元素
priority_queue only:
q.top(); //返回具有最高優先級的元素值,但不刪除該元素
stack范例函數:
stack<int> s;
stack< int, vector<int> > s2; //覆蓋基礎容器類型,使用vector實現stk
s.empty(); //判斷stack是否為空,為空返回true,否則返回false
s.size(); //返回stack中元素的個數
s.pop(); //刪除棧頂元素,但不返回其值
s.top(); //返回棧頂元素的值,但不刪除此元素
s.push(item); //在棧頂壓入新元素item
常用容器用法
序列式容器:vector、deque、list:每個元素都有固定位置——取決于插入時機和地點,和元素值無關
關聯式容器:set、multiset、map、multimap:元素位置取決于特定的排序準則,和插入順序無關
vector(begin,end || pop和push只有back)
1、構造函數
vector<type> vec:聲明一個元素類型為type的空vector
vector<type> vec(size):聲明一個元素類型為type的vector,元素個數為size
vector<type> vec(size, value):聲明一個元素類型為type的vector,元素個數為size,且值均為value
vector<type> obj(const vector&):復制構造函數
vector<type> obj(begin,end):復制[begin,end)區間數組的元素到vector中
2、增加函數
void push_back(const T& x):向量尾部增加一個元素X
iterator insert(iterator it,const T& x):向量中迭代器指向元素前增加一個元素x
iterator insert(iterator it,int n,const T& x):向量中迭代器指向元素前增加n個相同的元素x
iterator insert(iterator it,const_iterator first,const_iterator last):
向量中迭代器指向元素前插入另一個相同類型向量的[first,last)間的數據
3、刪除函數
iterator erase(iterator it):刪除向量中迭代器指向元素
iterator erase(iterator first,iterator last):刪除向量中[first,last)中元素
void pop_back():刪除向量中最后一個元素
void clear():清空向量中所有元素
4、遍歷函數
reference at(int pos):返回pos位置元素的引用
reference front():返回首元素的引用
reference back():返回尾元素的引用
iterator begin():返回向量頭指針,指向第一個元素
iterator end():返回向量尾指針,指向向量最后一個元素的下一個位置
reverse_iterator rbegin():反向迭代器,指向最后一個元素
reverse_iterator rend():反向迭代器,指向第一個元素之前的位置
5、判斷函數
bool empty() const:判斷向量是否為空,若為空,則向量中無元素
6、大小函數
int size() const:返回向量中元素的個數
int capacity() const:返回當前向量張紅所能容納的最大元素值
int max_size() const:返回最大可允許的vector元素數量值
7、其他函數
void swap(vector&):交換兩個同類型向量的數據
void assign(int n,const T& x):設置向量中第n個元素的值為x
void assign(const_iterator first,const_iterator last):向量中[first,last)中元素設置成當前向量元素
補,待換位子
reverse(obj.begin(),obj.end()); 從頭到尾進行反轉
sort(obj.begin(),obj.end()); 從頭到尾進行排序,第三個參數不寫,默認升序
sort(obj.begin(),obj.end(),compare);寫參數時可按下方格式創建bool值
bool compare(int a,int b)
{
return a< b; //升序排列,如果改為return a>b,則為降序
}
8、看著清楚
1.push_back 在數組的最后添加一個數據
2.pop_back 去掉數組的最后一個數據
3.erase 刪除指針指向的數據項
4.clear 清空當前的vector
5.empty 判斷vector是否為空
6.at 得到編號位置的數據
7.begin 得到數組頭的指針
8.end 得到數組的最后一個單元+1的指針
9.front 得到數組頭的引用
10.back 得到數組的最后一個單元的引用
11.rbegin 將vector反轉后的開始指針返回(其實就是原來的end-1)
12.rend 將vector反轉構的結束指針返回(其實就是原來的begin-1)
13.max_size 得到vector最大可以是多大
14.capacity 當前vector分配的大小
15.size 當前使用數據的大小
16.resize 改變當前使用數據的大小,如果它比當前使用的大,者填充默認值
17.reserve 改變當前vecotr所分配空間的大小
18.swap 與另一個vector交換數據
訪問方式
1、vector可以直接訪問(類似于數組的[ ]還有at( )方式和指針方式)
2、借由迭代器進行間接訪問
vector<int>::iterator it;//聲明一個迭代器,來訪問vector容器,作用:遍歷或者指向vector容器的元素
for(it=vec.begin();it!=vec.end();it++)
{
cout<<*it<<" ";
}
deque(front,back || pop和push有front和back)
雖然deque也提供Iterator,但它的迭代器并不是普通指針,其復雜度和vector不可同日而語。因此,我們應盡可能選擇使用vector而非deque。對deque進行的排序操作,為了最高效率,可將deque先完整復制到一個vector身上,將vector排序后(利用STL的sort算法),再復制回deque。
1、構造函數
#include<deque> // 頭文件
deque<type> deq; // 聲明一個元素類型為type的雙端隊列deque
deque<type> deq(size); // 聲明一個類型為type、含有size個默認值初始化元素的的雙端隊列deque
deque<type> deq(size, value); // 聲明一個元素類型為type、含有size個 value元素的雙端隊列deque
deque<type> deq(mydeque); // 復制構造函數
deque<type> deq(first,last); // 復制[first,last)區間數組的元素到deque中
2、
deq[ ]:用來訪問雙向隊列中單個的元素。
deq.front():返回第一個元素的引用。
deq.back():返回最后一個元素的引用。
deq.push_front(x):把元素x插入到雙向隊列的頭部。
deq.pop_front():彈出雙向隊列的第一個元素。
deq.push_back(x):把元素x插入到雙向隊列的尾部。
deq.pop_back():彈出雙向隊列的最后一個元素。
3、deque的一些特點
1.支持隨機訪問,即支持[ ]以及at(),但是性能沒有vector好。
2.可以在內部進行插入和刪除操作,但性能不及list。
3.deque兩端都能夠快速插入和刪除元素,而vector只能在尾端進行。
4.deque的元素存取和迭代器操作會稍微慢一些,因為deque的內部結構會多一個間接過程。
5.deque迭代器是特殊的智能指針,而不是一般指針,它需要在不同的區塊之間跳轉。
6.deque可以包含更多的元素,其max_size可能更大,因為不止使用一塊內存。
7.deque不支持對容量和內存分配時機的控制。
8.在除了首尾兩端的其他地方插入和刪除元素,都將會導致指向deque元素的任何pointers、references、iterators失效。不過,deque的內存重分配優于vector,因為其內部結構顯示不需要復制所有元素。
9.deque的內存區塊不再被使用時,會被釋放,deque的內存大小是可縮減的。不過,是不是這么做以及怎么做由實際操作版本定義。
10.deque不提供容量操作:capacity()和reverse(),但是vector可以。
訪問方式
1、deque同vector可以直接訪問(類似于數組的[ ]還有at( )方式和指針方式)
2、借由迭代器進行間接訪問
deque<int>::iterator it;//聲明一個迭代器,來訪問deque容器,作用:遍歷或者指向deque容器的元素
deque<int>::iterator it;
for (it = deq.begin(); it != deq.end(); it++)
{
cout << *it << ' ';
}
list()
list是stl實現的雙向鏈表,與向量(vectors)相比, 它允許快速的插入和刪除,但是隨機訪問卻比較慢。使用時需要添加頭文件
1、構造函數
list<type> lst; // 聲明一個元素類型為type的空list
list<type> lst(size); // 聲明一個類型為type、含有size個默認值初始化元素的的list
list<type> lst(size, value); //聲明一個元素類型為type、含有size個value元素的list
list<type> lst(mylist); // 復制構造函數
list<type> lst(begin,end); //復制[begin,end)區間數組的元素到deque中
2、常用函數
lst.assign() 給list賦值
lst.back() 返回最后一個元素
lst.begin() 返回指向第一個元素的迭代器
lst.clear() 刪除所有元素
lst.empty() 如果list是空的則返回true
lst.end() 返回末尾的迭代器
lst.erase() 刪除一個元素
lst.front() 返回第一個元素
lst.get_allocator() 返回list的配置器
lst.insert() 插入一個元素到list中
lst.max_size() 返回list能容納的最大元素數量
lst.merge() 合并兩個list
lst.pop_back() 刪除最后一個元素
lst.pop_front() 刪除第一個元素
lst.push_back() 在list的末尾添加一個元素
lst.push_front() 在list的頭部添加一個元素
lst.rbegin() 返回指向第一個元素的逆向迭代器
lst.remove() 從list刪除元素
lst.remove_if() 按指定條件刪除元素
lst.rend() 指向list末尾的逆向迭代器
lst.resize() 改變list的大小
lst.reverse() 把list的元素倒轉
lst.size() 返回list中的元素個數
lst.sort() 給list排序
lst.splice() 合并兩個list
lst.swap() 交換兩個list
lst.unique() 刪除list中相鄰重復的元素
lst.insert(++list1.begin(), 3, 9);在第一個元素后插入3個9