STL總結 (C++)

1、通常介紹

      STL(Standard Template Library),即標準模板庫,是一個具備工業強度的,高效的C++程序庫。它被容納於C++標準程序庫(C++ Standard Library)中,是ANSI/ISO C++標準中最新的也是極具革命性的一部分。該庫包含了諸多在計算機科學領域裏所經常使用的基本數據結構和基本算法。爲廣大C++程序員們提供了一個可擴展的應用框架,高度體現了軟件的可複用性。html

      從邏輯層次來看,在STL中體現了泛型化程序設計的思想(generic programming),引入了諸多新的名詞,好比像需求(requirements),概念(concept),模型(model),容器(container),算法(algorithmn),迭代子(iterator)等。與OOP(object-oriented programming)中的多態(polymorphism)同樣,泛型也是一種軟件的複用技術;node

       從實現層次看,整個STL是以一種類型參數化(type parameterized)的方式實現的,這種方式基於一個在早先C++標準中沒有出現的語言特性--模板(template)。若是查閱任何一個版本的STL源代碼,你就會發現,模板做爲構成整個STL的基石是一件千真萬確的事情。除此以外,還有許多C++的新特性爲STL的實現提供了方便;程序員

  在C++標準中,STL被組織爲下面的17個頭文件:<algorithm>、<deque>、<functional>、<iterator>、<array>、<vector>、<list>、<forward_list>、<map>、<unordered_map>、<memory>、<numeric>、<queue>、<set>、<unordered_set>、<stack>和<utility>。算法

 

2、STL的六大組件數組

  • 容器(Container),是一種數據結構,如list,vector,和deques ,以模板類的方法提供。爲了訪問容器中的數據,可使用由容器類輸出的迭代器;
  • 迭代器(Iterator),提供了訪問容器中對象的方法。例如,可使用一對迭代器指定list或vector中的必定範圍的對象。迭代器就如同一個指針。事實上,C++的指針也是一種迭代器。可是,迭代器也能夠是那些定義了operator*()以及其餘相似於指針的操做符地方法的類對象;
  • 算法(Algorithm),是用來操做容器中的數據的模板函數。例如,STL用sort()來對一個vector中的數據進行排序,用find()來搜索一個list中的對象,函數自己與他們操做的數據的結構和類型無關,所以他們能夠在從簡單數組到高度複雜容器的任何數據結構上使用;
  • 仿函數(Function object,仿函數(functor)又稱之爲函數對象(function object),其實就是重載了()操做符的struct,沒有什麼特別的地方
  • 迭代適配器(Adaptor)
  • 空間配製器(allocator)其中主要工做包括兩部分1.對象的建立與銷燬    2.內存的獲取與釋放

如下主要討論:容器,迭代器,算法,適配器。如欲詳加了解 參見C++ Primer 數據結構

 

1.STL容器框架

1)序列式容器(Sequence containers),每一個元素都有固定位置--取決於插入時機和地點,和元素值無關,vector、deque、list;less

   Vectors:將元素置於一個動態數組中加以管理,能夠隨機存取元素(用索引直接存取),數組尾部添加或移除元素很是快速。可是在中部或頭部安插元素比較費時;dom

   Deques:是「double-ended queue」的縮寫,能夠隨機存取元素(用索引直接存取),數組頭部和尾部添加或移除元素都很是快速。可是在中部或頭部安插元素比較費時;函數

   Lists:雙向鏈表,不提供隨機存取(按順序走到需存取的元素,O(n)),在任何位置上執行插入或刪除動做都很是迅速,內部只需調整一下指針;

2)關聯式容器(Associated containers),元素位置取決於特定的排序準則,和插入順序無關,set、multiset、map、multimap;

   Sets/Multisets:內部的元素依據其值自動排序,Set內的相同數值的元素只能出現一次,Multisets內可包含多個數值相同的元素,內部由二叉樹實現(實際上基於紅黑樹(RB-tree)實現),便於查找;

   Maps/Multimaps:Map的元素是成對的鍵值/實值,內部的元素依據其值自動排序,Map內的相同數值的元素只能出現一次,Multimaps內可包含多個數值相同的元素,內部由二叉樹實現(實際上基於紅黑樹(RB-tree)實現),便於查找;

另外有其餘容器hash_map,hash_set,hash_multiset,hash_multimap。

  容器的比較:

  Vector Deque List Set MultiSet Map MultiMap
內部結構 dynamic array array of arrays double linked list binary tree binary tree binary tree binary tree
隨機存取 Yes Yes No No No Yes(key) No
搜索速度 很慢
快速插入移除 尾部 首尾 任何位置 -- -- -- --

 

2.STL迭代器 

Iterator(迭代器)模式又稱Cursor(遊標)模式,用於提供一種方法順序訪問一個聚合對象中各個元素,
而又不需暴露該對象的內部表示。或者這樣說可能更容易理解:Iterator模式是運用於聚合對象的一種模式,經過運用該模式,使得咱們能夠在不知道對象內部表示的狀況下,按照必定順序(由iterator提供的方法)訪問聚合對象中的各個元素。

迭代器的做用:可以讓迭代器與算法不干擾的相互發展,最後又能無間隙的粘合起來,重載了*,++,==,!=,=運算符。用以操做複雜的數據結構,容器提供迭代器,算法使用迭代器;

常見的一些迭代器類型:iterator、const_iterator、reverse_iterator和const_reverse_iterator

迭代器通常聲明使用示例

vector<T>::iterator it;
list<T>::iterator it;
deque<T>::iterator it;

 

            input         output

              \            /  

                forward

                     |

                bidirectional

                     |

               random access                                       

 

 
 

要注意,上面這圖表並非代表它們之間的繼承關係:而只是描述了迭代器的種類和接口。處於圖表下層的迭代器都是相對於處於圖表上層迭代器的擴張集。例如:forward迭代器不但擁有input和output迭代器的全部功能,還擁有更多的功能。

各個迭代器的功能以下:

迭代器類別

說明

輸入

從容器中讀取元素。輸入迭代器只能一次讀入一個元素向前移動,輸入迭代器只支持一遍算法,同一個輸入迭代器不能兩遍遍歷一個序列

輸出

向容器中寫入元素。輸出迭代器只能一次一個元素向前移動。輸出迭代器只支持一遍算法,統一輸出迭代器不能兩次遍歷一個序列

正向

組合輸入迭代器和輸出迭代器的功能,並保留在容器中的位置

雙向

組合正向迭代器和逆向迭代器的功能,支持多遍算法

隨機訪問

組合雙向迭代器的功能與直接訪問容器中任何元素的功能,便可向前向後跳過任意個元素

迭代器的操做:

每種迭代器都可進行包括表中前一種迭代器可進行的操做。

迭代器操做

說明

全部迭代器

p++

後置自增迭代器

++p

前置自增迭代器

輸入迭代器

*p

復引用迭代器,做爲右值

p=p1

將一個迭代器賦給另外一個迭代器

p==p1

比較迭代器的相等性

p!=p1

比較迭代器的不等性

輸出迭代器

*p

復引用迭代器,做爲左值

p=p1

將一個迭代器賦給另外一個迭代器

正向迭代器

提供輸入輸出迭代器的全部功能

雙向迭代器

--p

前置自減迭代器

p--

後置自減迭代器

隨機迭代器

p+=i

將迭代器遞增i位

p-=i

將迭代器遞減i位

p+i

在p位加i位後的迭代器

p-i

在p位減i位後的迭代器

p[i]

返回p位元素偏離i位的元素引用

p<p1

若是迭代器p的位置在p1前,返回true,不然返回false

p<=p1

p的位置在p1的前面或同一位置時返回true,不然返回false

p>p1

若是迭代器p的位置在p1後,返回true,不然返回false

p>=p1

p的位置在p1的後面或同一位置時返回true,不然返回false

只有順序容器和關聯容器支持迭代器遍歷,各容器支持的迭代器的類別以下:

容器

支持的迭代器類別

說明

vector

隨機訪問

一種隨機訪問的數組類型,提供了對數組元素進行快速隨機訪問以及在序列尾部進行快速的插入和刪除操做的功能。能夠再須要的時候修改其自身的大小

deque

隨機訪問

一種隨機訪問的數組類型,提供了序列兩端快速進行插入和刪除操做的功能。能夠再須要的時候修改其自身的大小

list

雙向

一種不支持隨機訪問的數組類型,插入和刪除所花費的時間是固定的,與位置無關。

set

雙向

一種隨機存取的容器,其關鍵字和數據元素是同一個值。全部元素都必須具備唯一值。

multiset

雙向

一種隨機存取的容器,其關鍵字和數據元素是同一個值。能夠包含重複的元素。

map

雙向

一種包含成對數值的容器,一個值是實際數據值,另外一個是用來尋找數據的關鍵字。一個特定的關鍵字只能與一個元素關聯。

multimap

雙向

一種包含成對數值的容器,一個值是實際數據值,另外一個是用來尋找數據的關鍵字。一個關鍵字能夠與多個數據元素關聯。

stack

不支持

適配器容器類型,用vector,deque或list對象建立了一個先進後出容器

queue

不支持

適配器容器類型,用deque或list對象建立了一個先進先出容器

priority_queue

不支持

適配器容器類型,用vector或deque對象建立了一個排序隊列

 

 3.STL算法

STL算法部分主要由頭文件<algorithm>,<numeric>,<functional>組成。要使用 STL中的算法函數必須包含頭文件<algorithm>,對於數值算法須包含<numeric>,<functional>中則定義了一些模板類,用來聲明函數對象。
STL中算法大體分爲四類:
1)、非可變序列算法:指不直接修改其所操做的容器內容的算法。
2)、可變序列算法:指能夠修改它們所操做的容器內容的算法。
3)、排序算法:包括對序列進行排序和合並的算法、搜索算法以及有序序列上的集合操做。
4)、數值算法:對容器內容進行數值計算。

 

如下對全部算法進行細緻分類並標明功能:
    <一>查找算法(13個):判斷容器中是否包含某個值
    adjacent_find:            在iterator對標識元素範圍內,查找一對相鄰重複元素,找到則返回指向這對元素的第一個元素的ForwardIterator。不然返回last。重載版本使用輸入的二元操做符代替相等的判斷。
    binary_search:            在有序序列中查找value,找到返回true。重載的版本實用指定的比較函數對象或函數指針來判斷相等。
    count:                    利用等於操做符,把標誌範圍內的元素與輸入值比較,返回相等元素個數。
    count_if:                 利用輸入的操做符,對標誌範圍內的元素進行操做,返回結果爲true的個數。
    equal_range:              功能相似equal,返回一對iterator,第一個表示lower_bound,第二個表示upper_bound。
    find:                     利用底層元素的等於操做符,對指定範圍內的元素與輸入值進行比較。當匹配時,結束搜索,返回該元素的一個InputIterator。
    find_end:                 在指定範圍內查找"由輸入的另一對iterator標誌的第二個序列"的最後一次出現。找到則返回最後一對的第一個ForwardIterator,不然返回輸入的"另一對"的第一個ForwardIterator。重載版本使用用戶輸入的操做符代替等於操做。
    find_first_of:            在指定範圍內查找"由輸入的另一對iterator標誌的第二個序列"中任意一個元素的第一次出現。重載版本中使用了用戶自定義操做符。
    find_if:                  使用輸入的函數代替等於操做符執行find。
    lower_bound:              返回一個ForwardIterator,指向在有序序列範圍內的能夠插入指定值而不破壞容器順序的第一個位置。重載函數使用自定義比較操做。
    upper_bound:              返回一個ForwardIterator,指向在有序序列範圍內插入value而不破壞容器順序的最後一個位置,該位置標誌一個大於value的值。重載函數使用自定義比較操做。
    search:                   給出兩個範圍,返回一個ForwardIterator,查找成功指向第一個範圍內第一次出現子序列(第二個範圍)的位置,查找失敗指向last1。重載版本使用自定義的比較操做。
    search_n:                 在指定範圍內查找val出現n次的子序列。重載版本使用自定義的比較操做。
 
    <二>排序和通用算法(14個):提供元素排序策略
    inplace_merge:            合併兩個有序序列,結果序列覆蓋兩端範圍。重載版本使用輸入的操做進行排序。
    merge:                    合併兩個有序序列,存放到另外一個序列。重載版本使用自定義的比較。
    nth_element:              將範圍內的序列從新排序,使全部小於第n個元素的元素都出如今它前面,而大於它的都出如今後面。重載版本使用自定義的比較操做。
    partial_sort:             對序列作部分排序,被排序元素個數正好能夠被放到範圍內。重載版本使用自定義的比較操做。
    partial_sort_copy:        與partial_sort相似,不過將通過排序的序列複製到另外一個容器。
    partition:                對指定範圍內元素從新排序,使用輸入的函數,把結果爲true的元素放在結果爲false的元素以前。
    random_shuffle:           對指定範圍內的元素隨機調整次序。重載版本輸入一個隨機數產生操做。
    reverse:                  將指定範圍內元素從新反序排序。
    reverse_copy:             與reverse相似,不過將結果寫入另外一個容器。
    rotate:                   將指定範圍內元素移到容器末尾,由middle指向的元素成爲容器第一個元素。
    rotate_copy:              與rotate相似,不過將結果寫入另外一個容器。
    sort:                     以升序從新排列指定範圍內的元素。重載版本使用自定義的比較操做。
    stable_sort:              與sort相似,不過保留相等元素之間的順序關係。
    stable_partition:         與partition相似,不過不保證保留容器中的相對順序。
 
    <三>刪除和替換算法(15個)
    copy:                     複製序列
    copy_backward:            與copy相同,不過元素是以相反順序被拷貝。
    iter_swap:                交換兩個ForwardIterator的值。
    remove:                   刪除指定範圍內全部等於指定元素的元素。注意,該函數不是真正刪除函數。內置函數不適合使用remove和remove_if函數。
    remove_copy:              將全部不匹配元素複製到一個制定容器,返回OutputIterator指向被拷貝的末元素的下一個位置。
    remove_if:                刪除指定範圍內輸入操做結果爲true的全部元素。
    remove_copy_if:           將全部不匹配元素拷貝到一個指定容器。
    replace:                  將指定範圍內全部等於vold的元素都用vnew代替。
    replace_copy:             與replace相似,不過將結果寫入另外一個容器。
    replace_if:               將指定範圍內全部操做結果爲true的元素用新值代替。
    replace_copy_if:          與replace_if,不過將結果寫入另外一個容器。
    swap:                     交換存儲在兩個對象中的值。
    swap_range:               將指定範圍內的元素與另外一個序列元素值進行交換。
    unique:                   清除序列中重複元素,和remove相似,它也不能真正刪除元素。重載版本使用自定義比較操做。
    unique_copy:              與unique相似,不過把結果輸出到另外一個容器。
 
    <四>排列組合算法(2個):提供計算給定集合按必定順序的全部可能排列組合
    next_permutation:         取出當前範圍內的排列,並從新排序爲下一個排列。重載版本使用自定義的比較操做。
    prev_permutation:         取出指定範圍內的序列並將它從新排序爲上一個序列。若是不存在上一個序列則返回false。重載版本使用自定義的比較操做。
 

    <五>算術算法(4個)
    accumulate:               iterator對標識的序列段元素之和,加到一個由val指定的初始值上。重載版本再也不作加法,而是傳進來的二元操做符被應用到元素上。
    partial_sum:              建立一個新序列,其中每一個元素值表明指定範圍內該位置前全部元素之和。重載版本使用自定義操做代替加法。
    inner_product:            對兩個序列作內積(對應元素相乘,再求和)並將內積加到一個輸入的初始值上。重載版本使用用戶定義的操做。
    adjacent_difference:      建立一個新序列,新序列中每一個新值表明當前元素與上一個元素的差。重載版本用指定二元操做計算相鄰元素的差。
 
    <六>生成和異變算法(6個)
    fill:                     將輸入值賦給標誌範圍內的全部元素。
    fill_n:                   將輸入值賦給first到first+n範圍內的全部元素。
    for_each:                 用指定函數依次對指定範圍內全部元素進行迭代訪問,返回所指定的函數類型。該函數不得修改序列中的元素。
    generate:                 連續調用輸入的函數來填充指定的範圍。
    generate_n:               與generate函數相似,填充從指定iterator開始的n個元素。
    transform:                將輸入的操做做用與指定範圍內的每一個元素,併產生一個新的序列。重載版本將操做做用在一對元素上,另一個元素來自輸入的另一個序列。結果輸出到指定容器。
 

    <七>關係算法(8個)
    equal:                    若是兩個序列在標誌範圍內元素都相等,返回true。重載版本使用輸入的操做符代替默認的等於操做符。
    includes:                 判斷第一個指定範圍內的全部元素是否都被第二個範圍包含,使用底層元素的<操做符,成功返回true。重載版本使用用戶輸入的函數。
    lexicographical_compare:  比較兩個序列。重載版本使用用戶自定義比較操做。
    max:                      返回兩個元素中較大一個。重載版本使用自定義比較操做。
    max_element:              返回一個ForwardIterator,指出序列中最大的元素。重載版本使用自定義比較操做。
    min:                      返回兩個元素中較小一個。重載版本使用自定義比較操做。
    min_element:              返回一個ForwardIterator,指出序列中最小的元素。重載版本使用自定義比較操做。
    mismatch:                 並行比較兩個序列,指出第一個不匹配的位置,返回一對iterator,標誌第一個不匹配元素位置。若是都匹配,返回每一個容器的last。重載版本使用自定義的比較操做。
 

    <八>集合算法(4個)
    set_union:                構造一個有序序列,包含兩個序列中全部的不重複元素。重載版本使用自定義的比較操做。
    set_intersection:         構造一個有序序列,其中元素在兩個序列中都存在。重載版本使用自定義的比較操做。
    set_difference:           構造一個有序序列,該序列僅保留第一個序列中存在的而第二個中不存在的元素。重載版本使用自定義的比較操做。
    set_symmetric_difference: 構造一個有序序列,該序列取兩個序列的對稱差集(並集-交集)。
 

   <九>堆算法(4個)
    make_heap:                把指定範圍內的元素生成一個堆。重載版本使用自定義比較操做。
    pop_heap:                 並不真正把最大元素從堆中彈出,而是從新排序堆。它把first和last-1交換,而後從新生成一個堆。可以使用容器的back來訪問被"彈出"的元素或者使用pop_back進行真正的刪除。重載版本使用自定義的比較操做。
    push_heap:                假設first到last-1是一個有效堆,要被加入到堆的元素存放在位置last-1,從新生成堆。在指向該函數前,必須先把元素插入容器後。重載版本使用指定的比較操做。
    sort_heap:                對指定範圍內的序列從新排序,它假設該序列是個有序堆。重載版本使用自定義比較操做。

 

4.適配器

STL提供了三個容器適配器:queue、priority_queue、stack。這些適配器都是包裝了vector、list、deque中某個順序容器的包裝器。注意:適配器沒有提供迭代器,也不能同時插入或刪除多個元素。下面對各個適配器進行歸納總結。


(1)stack用法

#include <stack>
template < typename T, typename Container=deque > class stack;

可使用三個標準順序容器vecotr、deque(默認)、list中的任何一個做爲stack的底層模型。

bool stack<T>::empty()                               //判斷堆棧是否爲空
void stack<T>::pop()                                 //彈出棧頂數據
stack<T>::push(T x)                                  //壓入一個數據
stack<T>::size_type stack<T>::size()                 //返回堆棧長度
T stack<T>::top()                                    //獲得棧頂數據

 代碼示例:

stack<int> intDequeStack;  
stack<int,vector<int>> intVectorStack;  
stack<int,list<int>> intListStack; 

 


(2)queue用法

#include <queue>
template<typename T, typename Container = deque<T> > class  queue;

第一個參數指定要在queue中存儲的類型,第二個參數規定queue適配的底層容器,可供選擇的容器只有dequeue和list。對大多數用途使用默認的dequeue。

複製代碼
queue<T>::push(T x)
void queue<T>::pop()
T queue<T>::back()
T queue<T>::front()
queue<T>::size_type 
queue<T>::size()
bool queue<T>::empty()
複製代碼

代碼示例:

queue<int> intDequeQueue;    
queue<int,list<int>> intListQueue;

 


(3)priority_queue用法

#include <queue>
template <typename T, typename Container = vector<T>, typename Compare = less<T> > class priority_queue;

priority_queue也是一個隊列,其元素按有序順序排列。其不採用嚴格的FIFO順序,給定時刻位於隊頭的元素正是有最高優先級的元素。若是兩個元素有相同的優先級,那麼它們在隊列中的順序就遵循FIFO語義。默認適配的底層容器是vector,也可使用deque,list不能用,由於priority_queue要求能對元素隨機訪問以便進行排序。

複製代碼
priority_queue<T>::push(T x)
void priority_queue<T>::pop()
T priority_queue<T>::top()
priority_queue<T>::size_type 
priority_queue<T>::size()
bool priority_queue<T>::empty()
複製代碼

代碼示例:

priority_queue< int, vector<int>, greater<int> >
priority_queue< int, list<int>, greater<int> >

 

標準庫默認使用元素類型的<操做符來肯定它們之間的優先級關係,用法有三:(下文轉自http://www.cnblogs.com/vvilp/articles/1504436.html)

優先隊列第一種用法,經過默認使用的<操做符可知在整數中元素大的優先級高。

priority_queue<int> qi; 

示例中輸出結果爲:9 6 5 3 2

優先隊列第二種用法,創建priority_queue時傳入一個比較函數,使用functional.h函數對象做爲比較函數。

priority_queue<int, vector<int>, greater<int> >qi2;

示例2中輸出結果爲:2 3 5 6 9

優先隊列第三種用法,是自定義優先級。

複製代碼
struct node 
{
     friend bool operator< (node n1, node n2)
     {
         return n1.priority < n2.priority;
     } 
     int priority;
     int value; 
}; 
priority_queue<node> qn; 
複製代碼

在示例3中輸出結果爲:

優先級  值

9          5

8          2

6          1

2          3

1          4

在該結構中,value爲值,priority爲優先級。經過自定義operator<操做符來比較元素中的優先級。注意:必須是自定義<操做符才行,把上述的結構中的<操做符改爲>編譯不經過。

相關文章
相關標籤/搜索