STL 總結

原文地址:http://blog.csdn.net/Image_Graphics/archive/2007/08/21/1753340.aspx

STL(Standard Template Library)是C++標準庫的一部分(80%),是用C++ Template機制來表達泛型的庫。

STL,成功的將算法與數據結構分離,在沒有效率損失的前提下,得到了及大的彈性。

六大組件
容器(Container)
算法(Algorithm)
迭代器(Iterator)
仿函數(Function object)
適配器(Adaptor)
空間配製器(allocator)

Set,Map都不能用push_back,push_front,因爲它是自動排序的。
Sets/Multisets
內部的元素依據其值自動排序

Set內的相同數值的元素只能出現一次,Multisets內可包含多個數值相同的元素。

內部由二叉樹實現,便於查找。

Maps/Multimaps
Map的元素是成對的鍵值/實值,內部的元素依據其值自動排序。

Map內的相同數值的元素只能出現一次,Multimaps內可包含多個數值相同的元素。

內部由二叉樹實現,便於查找。

所有容器的共同操作

一。所有容器都提供了一個默認的構造函數,一個拷貝構造函數。
例:
list l;
....
vector ivector(l.begin(),l.end());

int array[]={1,2,3,4};
....
set iset(array,array+sizeof(array)/sizeof(array[0]));

二。與大小相關的函數
size(),empty(),max_size()

三。返回迭代器的函數
begin(),end(),rbegin(),rend()

四。比較操作
==,!=,<,>,>=....

Vector詳解:
capacity(),返回vector能夠容納的元素個數。
size(),返回vector內現有元素的個數。
賦值操作:
c1=c2; 把c2的全部元素指派給c1
c.assign(n,elem);複製n個elem,指派給c
c.assign(beg,end);將區間beg,end內的元素指派給c
c1.swap(c2);將c1,c2元素互換
swap(c1,c2);同上
元素存取
c.at(index);
c[index];
c.front();返回第一個元素
c.back();

插入和刪除:
c.insert(pos.elem);
c.insert(pos,n.elem); 插入n個elem
c.insert(pos,beg,end); 在pos出插入beg,end區間內的所有元素。
c.push_back(elem);
c.pop_back();
c.erase(pos); 刪除pos上的元素,返回下一個元素
c.erase(beg,end);
c.resize(num);將元素數量改爲num,如果size變大了,多出來的新元素都要一default方式構建。
c.resize(num,elem);將元素數量改爲num,如果size變大了,多出來的新元素是elem的副本。
c.clear();刪除所有。

vector的reserve和resize
reserve只分配空間,而不創建對象,size()不變。而resize分配空間而且用空對象填充.

reserve是容器預留空間,但並不真正創建元素對象,在創建對象之前,不能引用容器內的元素,因此當加入新的元素時,需要用push_back()/insert()函數。

resize是改變容器的大小,並且創建對象,因此,調用這個函數之後,就可以引用容器內的對象了,因此當加入新的元素時,用operator[]操作符,或者用迭代器來引用元素對象。

再者,兩個函數的形式是有區別的,reserve函數之後一個參數,即需要預留的容器的空間;resize函數可以有兩個參數,第一個參數是容器新的大小,第二個參數是要加入容器中的新元素,如果這個參數被省略,那麼就調用元素對象的默認構造函數。

vector有而deque無的:capacity(), reserve();
deque有而vector無的:push_front(elem), pop_front(); push_back(elem), pop_back();

STL提供的另兩種容器queue、stack,其實都只不過是一種adaptor,它們簡單地修飾deque的界面而成爲另外的容器類型

List詳解:

for_each  (.begin(), .end(), “函數”);
count (.begin(), .end(), 100, jishuqi);
返回對象等於100的個數jishuqi值。

count_if() 帶一個函數對象的參數(上面“100”的這個參數)。函數對象是一個至少帶有一個operator()方法的類。這個類可以更復雜。

find(*.begin().*end(),“要找的東西”);
如果沒有找到指出的對象,就會返回*.end()的值,要是找到了就返回一個指着找到的對象的iterator
fine_if();與count_if()類似,是find的更強大版本。

STL通用算法search()用來搜索一個容器,但是是搜索一個元素串,不象find()和find_if() 只搜索單個的元素。

search算法在一個序列中找另一個序列的第一次出現的位置。
search(A.begin(), A.end(), B.begin(), B.end());
在A中找B這個序列的第一次出現。

要排序一個list,我們要用list的成員函數sort(),而不是通用算法sort()。

list容器有它自己的sort算法,這是因爲通用算法僅能爲那些提供隨機存取裏面元素 的容器排序。

list的成員函數push_front()和push_back()分別把元素加入到list的前面和後面。你可以使用insert() 把對象插入到list中的任何地方。
insert()可以加入一個對象,一個對象的若干份拷貝,或者一個範圍以內的對象。

list成員函數pop_front()刪掉list中的第一個元素,pop_back()刪掉最後一個元素。 函數erase()刪掉由一個iterator指出的元素。還有另一個erase()函數可以刪掉一個範圍的元素。

list的成員函數remove()用來從list中刪除元素。
*.remove("要刪除的對象");

通用算法remove()使用和list的成員函數不同的方式工作。一般情況下不改變容器的大小。

remove(*.begin(),*.end(),"要刪除的對象");

使用STL通用算法stable_partition()和list成員函數splice()來劃分一個list。
stable_partition()是一個有趣的函數。它重新排列元素,使得滿足指定條件的元素排在 不滿足條件的元素前面。它維持着兩組元素的順序關係。
splice 把另一個list中的元素結合到一個list中。它從源list中刪除元素。

Set Map詳解:

STL map和set的使用雖不復雜,但也有一些不易理解的地方,如:

爲何map和set的插入刪除效率比用其他序列容器高?
爲何每次insert之後,以前保存的iterator不會失效?
爲何map和set不能像vector一樣有個reserve函數來預分配數據?
當數據元素增多時(10000到20000個比較),map和set的插入和搜索速度變化如何?

C++ STL中標準關聯容器set, multiset, map, multimap內部採用的就是一種非常高效的平衡檢索二叉樹:紅黑樹,也成爲RB樹(Red-Black Tree)。RB樹的統計性能要好於一般的平衡二叉樹(AVL-樹).

爲何map和set的插入刪除效率比用其他序列容器高?

大部分人說,很簡單,因爲對於關聯容器來說,不需要做內存拷貝和內存移動。說對了,確實如此。map和set容器內所有元素都是以節點的方式來存儲,其節點結構和鏈表差不多,指向父節點和子節點。這裏的一切操作就是指針換來換去,和內存移動沒有關係。

爲何每次insert之後,以前保存的iterator不會失效?(同解)

爲何map和set不能像vector一樣有個reserve函數來預分配數據?

究其原理來說時,引起它的原因在於在map和set內部存儲的已經不是元素本身了,而是包含元素的節點。
其實你就記住一點,在map和set內面的分配器已經發生了變化,reserve方法你就不要奢望了。
詳細的實現參看STL中的Allocator

當數據元素增多時(10000和20000個比較),map和set的插入和搜索速度變化如何?

如果你知道log2的關係你應該就徹底瞭解這個答案。在map和set中查找是使用二分查找,也就是說,如果有16個元素,最多需要比較4次就能找到結果,有32個元素,最多比較5次。那麼有10000個呢?最多比較的次數爲log10000,最多爲14次,如果是20000個元素呢?最多不過15次。

泛型算法:
所有算法的前兩個參數都是一對iterators:[first,last),用來指出容器內一個範圍內的元素。
每個算法的聲明中,都表現出它所需要的最低層次的iterator類型。

70個算法:
accumulate() 元素累加
adjacent_difference() 相鄰元素的差額
adjacent_find() 搜尋相鄰的重複元素
binary_search() 二元搜尋
copy() 複製
copy_backward() 逆向複製
count() 計數
count_if() 在特定條件下計數
equal() 判斷相等與否
equal_range() 判斷相等與否(傳回一個上下限區間範圍)
fill() 改填元素值
fill_n() 改填元素值,n 次
find() 搜尋
find_if() 在特定條件下搜尋
find_end() 搜尋某個子序列的最後一次出現地點
find_first_of() 搜尋某些元素的首次出現地點
for_each() 對範圍內的每一個元素施行某動作
generate() 以指定動作的運算結果充填特定範圍內的元素
generate_n() 以指定動作的運算結果充填 n 個元素內容
includes() 涵蓋於
inner_product() 內積
inplace_merge() 合併並取代(覆寫)
iter_swap() 元素互換
lexicographical_compare() 以字典排列方式做比較
lower_bound() 下限
max() 最大值
max_element() 最大值所在位置
min() 最小值
min_element() 最小值所在位置
merge() 合併兩個序列
mismatch() 找出不吻合點
next_permutation() 獲得下一個排列組合
泛型演算法(Generic Algorithms)與 Function Obje4 cts
nth_element() 重新安排序列中第n個元素的左右兩端
partial_sort() 局部排序
partial_sort_copy() 局部排序並複製到它處
partial_sum() 局部總和
partition() 切割
prev_permutation() 獲得前一個排列組合
random_shuffle() 隨機重排
remove() 移除某種元素(但不刪除)
remove_copy() 移除某種元素並將結果複製到另一個 container
remove_if() 有條件地移除某種元素
remove_copy_if() 有條件地移除某種元素並將結果複製到另一個 container
replace() 取代某種元素
replace_copy() 取代某種元素,並將結果複製到另一個 container
replace_if() 有條件地取代
replace_copy_if() 有條件地取代,並將結果複製到另一個 container
reverse() 顛倒元素次序
reverse_copy() 顛倒元素次序並將結果複製到另一個 container
rotate() 旋轉
rotate_copy() 旋轉,並將結果複製到另一個 container
search() 搜尋某個子序列
search_n() 搜尋「連續發生 n 次」的子序列
set_difference() 差集
set_intersection() 交集
set_symmetric_difference() 對稱差集
set_union() 聯集
sort() 排序
stable_partition() 切割並保持元素相對次序
stable_sort() 排序並保持等值元素的相對次序
swap() 置換(對調)
swap_range() 置換(指定範圍)
transform() 以兩個序列爲基礎,交互作用產生第三個序列
unique() 將重複的元素摺疊縮編,使成唯一
unique_copy() 將重複的元素摺疊縮編,使成唯一,並複製到他處
upper_bound() 上限
-- 以下是 heap 相關演算法 --
make_heap() 製造一個 heap
pop_heap() 從 heap 內取出一個元素
push_heap() 將一個元素推進 heap 內
sort_heap() 對 heap 排序

以下內容來自 《More Effctive STL》:

● 標準STL序列容器:vector、string、deque和list。
● 標準STL關聯容器:set、multiset、map和multimap。

● 非標準序列容器slist和rope。slist是一個單向鏈表,rope本質上是一個重型字符串。(“繩子
(rope)”是重型的“線(string)”。明白了嗎?)
● 非標準關聯容器hash_set、hash_multiset、hash_map和hash_multimap。
● vector可以作爲string的替代品。
● vector作爲標準關聯容器的替代品。,有時候vector可以在時間和空間上都表現得比
標準關聯容器好。
● 幾種標準非STL容器,包括數組、bitset、valarray、stack、queue和priority_queue。
vector、list和deque提供給程序員不同的複雜度,因此應該這麼用:vector是一種可以默認使用
的序列類型,當很頻繁地對序列中部進行插入和刪除時應該用list,當大部分插入和刪除發生
在序列的頭或尾時可以選擇deque這種數據結構。

● 標準的連續內存容器是vector、string和deque。非標準的rope也是連續內存容器。
●表現爲鏈表的容器——比如list和slist——是基於節點的,所有的標準關聯容器也是(它們的典型實現是平衡樹)。非標準的散列容器使用不同的基於節點的實現.

●用empty來代替檢查size()是否爲0
●避免使用vector

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