C++之容器
容器,迭代器與容器適配器
所謂容器,即是將最常運用的一些數據結構(data structures)用類模板實現出來,用于容納特定類型的對象。根據數據在容器中排列的特性,容器可概分為序列式(sequence)和關聯式(associative)兩種。容器的好處,那就是它不需要你預先告訴它你要存儲多少對象,只要你創建一個容器對象,并合理的調用它所提供的方法,所有的處理細節將由容器來自身完成,它可以為你申請內存或釋放內存,并且用最優的算法來執行您的命令。
迭代器是一種檢查容器內元素并遍歷元素的數據類型,它提供類似指針的功能,用于對容器的內容進行走訪。
適配器是使一事物的行為類似于另一事物的行為的一種機制,是讓一種已存在的容器類型采用另一種不同的抽象類型的工作方式來實現的一種機制。我們可以把它理解為容器的接口,或者容器的模版。而適配器具體采用哪種容器類型去實現,在定義適配器的時候可以決定。
?
下表列出STL?定義的三類容器所包含的具體容器類:
| 標準容器類 | 特點 |
| 順序性容器 | |
| vector | 從后面快速的插入與刪除,直接訪問任何元素 |
| deque | 從前面或后面快速的插入與刪除,直接訪問任何元素 |
| list | 雙鏈表,從任何地方快速插入與刪除 |
| 關聯容器 | |
| set | 快速查找,不允許重復值 |
| multiset | 快速查找,允許重復值 |
| map | 一對多映射,基于關鍵字快速查找,不允許重復值 |
| multimap | 一對多映射,基于關鍵字快速查找,允許重復值 |
| 容器適配器 | |
| stack | 后進先出 |
| queue | 先進先出 |
| priority_queue | 最高優先級元素總是第一個出列 ? |
序列式容器(順序容器)
定義和初始化:
為了定義一個容器類型的對象,必須包含相關的頭文件:
#include<vector>
#include<list>
#include<deque>
由于所有的容器都是類模板,因此,當我們要定義某種容器對象時,必須在容器名后面加一對尖括號,尖括號里面提供容器中存放的元素的類型:
vector<string> svec;//此時該容器是空的,不過它可以存放string對象
類似的如:
list<int> ?listInt;
deque<Person> item;
所有的容器類型都定義了默認構造函數,用于創建指定類型的空容器對象,為了程序更清晰,簡短,容器類型最常用的構造函數是默認構造函數,不過,容器類還提供了以下的構造函數:
C c(c2);//創建容器c2的副本c,c和c2必須具有相同的容器類型,并存放相同類型的元素,它適用于所有的容器
將一個容器復制給另外一個容器時,類型必須匹配:容器類型和元素類型都必須匹配;
vector<int> ivec;
vector<int> ivec2(ivec);
?
C c(b,e);//創建c,其元素是迭代器b和e標示的范圍內元素的副本,適用于所有容器
盡管不能直接將一種容器內的元素復制給另外一種容器,但系統允許通過一對迭代器間接實現該功能。因此,使用迭代器時,不要求容器類型相同,容器內的元素類型也可以不相同,只要它們相互兼容,能夠將要復制的元素轉換為所構建的新容器的元素類型即可實現復制。
vector<string> svec;
list<string> slist(svec.begin(),svec.end());
vector<string>::iterator mid=svec.begin()+svec.size()/2;
deque<string> front(svec.begin(),mid);
deque<string> back(mid,svec.end());
由于指針就是迭代器,因此允許通過使用內置數組中的一對指針初始化容器:
char *words[]={"book","book","book"};
size_t words_size=sizeof(words)/sizeof(char*);
list<string> word2(words,words+words_size);
?
?
C c(n,t);//用n個值為t的元素創建容器c,其中值t必須是容器類型C的元素類型的值,或者是可以轉換為該類型的值,它只適用于順序容器
list<string> slist(64,"hello");//64個“hello"
C c(n);//創建有n個值初始化元素的容器c,只適用于順序容器
list<int> ilist(64);//64個元素,每個都是0
?
容器內元素的類型約束:
容器在給我們提供了強大的功能的同時,也給我們提出了一些使用要求,順序容器元素類型必須滿足以下兩個約束:
(1)元素類型必須是支持賦值運算
(2)元素類型的對象必須可以復制
引用不支持一般意義的賦值運算,因此,除了引用類型外,所有內置或復合類型都可以用在元素類型;IO庫類型不支持賦值和復制,因此除了輸入輸出(IO)標準庫類型外,所有的其他標準庫類型都是有效的容器元素類型,甚至可以是元素本身就是容器類型元素如:
vector<vector<string> > lines;
此外,我們應該明白的,那就是以上的兩個約束只是容器類型的最低要求,因為,一些容器操作對元素類型提出了更苛刻的要求,提出了其他約束,如果元素類型不支持這些額外的苛刻要求,那我們還是可以定義該類型的容器,但是不能使用相應的特定的操作。
迭代器
迭代器為所有標準庫類型所提供的運算:
*iter ? 返回迭代器iter所指向的元素的引用
iter->member 對iter進行解引用,獲取指定元素中名為member的成員,等效于(*iter).member
++iter ?給iter加1,使其指向容器里的下一個元素
iter++?
--iter 給iter減1,使其指向容器里的前一個元素
iter--
iter1==iter2 比較兩個迭代器是否相等,當兩個迭代器指向同一個容器中的銅一個元素,或者當它們都指向同一個容器的超出末端的下一個位置,兩個迭代器相等
iter1 !=iter2
?
C++定義中的容器類型中,只有vector和deque容器提供下面兩種重要的運算:迭代器算術運算,以及使用除了==和!=之外的關系操作符來比較兩個迭代器:
iter+n
iter-n 在迭代器上加(減)整數值n,將產生指向容器前面(后面)第n個元素的迭代器
iter1+=iter2
iter1-=iter2
iter1-iter2
<,<=,>,>= ?迭代器的關系操作符,當一個迭代器指向的元素在容器中位于另一個迭代器指向的元素之前,則前一個迭代器小于后一個迭代器
?
C++語言使用一對迭代器標記迭代器范圍,這兩個迭代器分別指向同一個容器中的兩個元素或超出末端的下一個位置,通常將它們命名為first和last,或beg和end,用于標記容器中的一段元素范圍。要注意的是,last(或者end)并不是指向元素范圍的最后一個元素,而是指向最后一個元素的下一位置,這樣更方便我們編程使用:當first和last相等時,迭代器范圍為空,當first與last不相等的時候,迭代器范圍內至少有一個元素,而且first指向該區間中的第一個元素:
while(first !=last)
{
? ?++first;
}
?
begin和end成員
begin和end操作產生指向這些容器內第一個元素和最后一個元素的下一個位置的迭代器
c.begin()?返回一個迭代器,它指向容器c的第一個元素
c.end()?返回一個迭代器,它指向容器c的最后一個元素的下一個位置
c.rbegin()?返回一個逆序迭代器,它指向容器c的最后一個元素
c.rend()?返回一個逆序迭代器,它指向容器c的第一個元素前面的位置?
反向迭代器是一種反向遍歷容器的迭代器。也就是,從最后一個元素到第一個元素遍歷容器。反向迭代器將自增(和自減)的含義反過來了:對于反向迭代器,++ 運算將訪問前一個元素,而 -- 運算則訪問下一個元素,如下圖:
上述每個操作都有兩個不同的版本:一個是const成員,另一個是非const成員。這些操作返回什么類型取決于容器是否為const。如果容器不是const,則這些操作返回iterator或reverse_iterator類型。如果容器是const,則其返回類型要加上const_前綴,也就是const_iterator和const_reverse_iterator類型。
?
在順序容器中添加元素
c.push_back(t); 在容器c的尾部添加值為t的元素,返回void類型
c.push_front(t);在容器c的前端添加值為t的元素,返回void類型
只適用于list和deque容器類型
c.insert(p,t);在迭代器p所指向的元素前面插入值為t的新元素,返回指向新添加元素的迭代器
c.insert(p,n,t);在迭代器p所指向的元素前面插入n個值為t的新元素,返回void類型
c.insert(p,b,e);在迭代器p所指向的元素前面插入由迭代器b和e標記的范圍內的元素,返回void類型
在容器中添加元素時,系統是將元素值復制到容器里,類似地,使用一段元素初始化新容器時,新容器存放的是原始元素的副本。被復制的元素和新容器中的元素各不相干,此后,容器內元素值發生變化時,被復制的原始元素值不受到影響,反之亦然。
?
順序容器的大小操作
c.size() 返回容器 c 中的元素個數。返回類型為 c::size_type
c.max_size() 返回容器 c 可容納的最多元素個數,返回類型為c::size_type
c.empty() 返回標記容器大小是否為 0 的布爾值
c.resize(n) 調整容器 c 的長度大小,使其能容納 n 個元素,如果 n <c.size(),則刪除多出來的元素;否則,添加采用值初始化的新元素
c.resize(n,t) 調整容器 c 的長度大小,使其能容納 n 個元素。所有新添加的元素值都為 t
?
?
?訪問容器內元素:
c.back() 返回容器c的最后一個元素的引用(注意與前面end或者last的區別)
c.front() 返回容器c的第一個元素的引用
以下兩種只適用于vector和deque容器
c[n] 返回下標為n的元素的引用
c.at(n)返回下標為n的元素的引用
?
刪除容器元素:
c.erase(p) 刪除迭代器p所指向的元素,返回一個指向被刪除元素后面的元素的迭代器
c.erase(b,e) 刪除迭代器b和e所標記的范圍內的所有元素
c.clear()?刪除迭代器c內的所有元素
c.pop_back()刪除迭代器c內的最后一個元素
c.front()刪除迭代器c內的第一個元素
轉載于:https://www.cnblogs.com/kunhu/p/3621128.html
總結
- 上一篇: 旅行1:丽江
- 下一篇: SugarSync网盘之XML解析