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