關(guān)于STL中l(wèi)ist容器的一些總結(jié)
1.關(guān)于list容器
list是一種序列式容器。list容器完成的功能實(shí)際上和數(shù)據(jù)結(jié)構(gòu)中的雙向鏈表是極其相似的,list中的數(shù)據(jù)元素是通過(guò)鏈表指針串連成邏輯意義上的線性表,也就是list也具有鏈表的主要優(yōu)點(diǎn),即:在鏈表的任一位置進(jìn)行元素的插入、刪除操作都是快速的。list的實(shí)現(xiàn)大概是這樣的:list的每個(gè)節(jié)點(diǎn)有三個(gè)域:前驅(qū)元素指針域、數(shù)據(jù)域和后繼元素指針域。前驅(qū)元素指針域保存了前驅(qū)元素的首地址;數(shù)據(jù)域則是本節(jié)點(diǎn)的數(shù)據(jù);后繼元素指針域則保存了后繼元素的首地址。其實(shí),list和循環(huán)鏈表也有相似的地方,即:頭節(jié)點(diǎn)的前驅(qū)元素指針域保存的是鏈表中尾元素的首地址,list的尾節(jié)點(diǎn)的后繼元素指針域則保存了頭節(jié)點(diǎn)的首地址,這樣,list實(shí)際上就構(gòu)成了一個(gè)雙向循環(huán)鏈。由于list元素節(jié)點(diǎn)并不要求在一段連續(xù)的內(nèi)存中,顯然在list中是不支持快速隨機(jī)存取的,因此對(duì)于迭代器,只能通過(guò)“++”或“--”操作將迭代器移動(dòng)到后繼/前驅(qū)節(jié)點(diǎn)元素處。而不能對(duì)迭代器進(jìn)行+n或-n的操作,這點(diǎn),是與vector等不同的地方。
我想把三個(gè)常用的序列式放在一起對(duì)比一下是有必要的:
vector :vector和built-in數(shù)組類似,擁有一段連續(xù)的內(nèi)存空間,能非常好的支持隨即存取,即[]操作符,但由于它的內(nèi)存空間是連續(xù)的,所以在中間進(jìn)行插入和刪除會(huì)造成內(nèi)存塊的拷貝,另外,當(dāng)插入較多的元素后,預(yù)留內(nèi)存空間可能不夠,需要重新申請(qǐng)一塊足夠大的內(nèi)存并把原來(lái)的數(shù)據(jù)拷貝到新的內(nèi)存空間。這些影響了vector的效率,但是實(shí)際上用的最多的還是vector容器,建議大多數(shù)時(shí)候使用vector效率一般是不錯(cuò)的。
list:list就是數(shù)據(jù)結(jié)構(gòu)中的雙向鏈表(根據(jù)sgi stl源代碼),因此它的內(nèi)存空間是不連續(xù)的,通過(guò)指針來(lái)進(jìn)行數(shù)據(jù)的訪問(wèn),這個(gè)特點(diǎn)使得它的隨即存取變的非常沒(méi)有效率,因此它沒(méi)有提供[]操作符的重載。但由于鏈表的特點(diǎn),它可以以很好的效率支持任意地方的刪除和插入。
deque:deque是一個(gè)double-ended queue,它的具體實(shí)現(xiàn)不太清楚,但知道它具有以下兩個(gè)特點(diǎn):它支持[]操作符,也就是支持隨即存取,并且和vector的效率相差無(wú)幾,它支持在兩端的操作:push_back,push_front,pop_back,pop_front等,并且在兩端操作上與list的效率也差不多。
因此在實(shí)際使用時(shí),如何選擇這三個(gè)容器中哪一個(gè),應(yīng)根據(jù)你的需要而定,具體可以遵循下面的原則:
1. 如果你需要高效的隨即存取,而不在乎插入和刪除的效率,使用vector
2. 如果你需要大量的插入和刪除,而不關(guān)心隨即存取,則應(yīng)使用list
3. 如果你需要隨即存取,而且關(guān)心兩端數(shù)據(jù)的插入和刪除,則應(yīng)使用deque。
2.list中常用的函數(shù)
2.1 list中的構(gòu)造函數(shù):
list() 聲明一個(gè)空列表;
list(n) 聲明一個(gè)有n個(gè)元素的列表,每個(gè)元素都是由其默認(rèn)構(gòu)造函數(shù)T()構(gòu)造出來(lái)的
list(n,val) 聲明一個(gè)由n個(gè)元素的列表,每個(gè)元素都是由其復(fù)制構(gòu)造函數(shù)T(val)得來(lái)的
list(n,val) 聲明一個(gè)和上面一樣的列表
list(first,last) 聲明一個(gè)列表,其元素的初始值來(lái)源于由區(qū)間所指定的序列中的元素
--------------------------------------------------------------------------------
2.2 begin()和end():通過(guò)調(diào)用list容器的成員函數(shù)begin()得到一個(gè)指向容器起始位置的iterator,可以調(diào)用list容器的 end() 函數(shù)來(lái)得到list末端下一位置,相當(dāng)于:int a[n]中的第n+1個(gè)位置a[n],實(shí)際上是不存在的,不能訪問(wèn),經(jīng)常作為循環(huán)結(jié)束判斷結(jié)束條件使用。
--------------------------------------------------------------------------------
2.3 push_back() 和push_front():使用list的成員函數(shù)push_back和push_front插入一個(gè)元素到list中。其中push_back()從list的末端插入,而 push_front()實(shí)現(xiàn)的從list的頭部插入。
--------------------------------------------------------------------------------
2.4 empty():利用empty() 判斷l(xiāng)ist是否為空。
--------------------------------------------------------------------------------
2.5 resize(): 如果調(diào)用resize(n)將list的長(zhǎng)度改為只容納n個(gè)元素,超出的元素將被刪除,如果需要擴(kuò)展那么調(diào)用默認(rèn)構(gòu)造函數(shù)T()將元素加到list末端。如果調(diào)用resize(n,val),則擴(kuò)展元素要調(diào)用構(gòu)造函數(shù)T(val)函數(shù)進(jìn)行元素構(gòu)造,其余部分相同。
--------------------------------------------------------------------------------
2.6 clear(): 清空l(shuí)ist中的所有元素。
--------------------------------------------------------------------------------
2.7 front()和back(): 通過(guò)front()可以獲得list容器中的頭部元素,通過(guò)back()可以獲得list容器的最后一個(gè)元素。但是有一點(diǎn)要注意,就是list中元素是空的時(shí)候,這時(shí)候調(diào)用front()和back()會(huì)發(fā)生什么呢?實(shí)際上會(huì)發(fā)生不能正常讀取數(shù)據(jù)的情況,但是這并不報(bào)錯(cuò),那我們編程序時(shí)就要注意了,個(gè)人覺(jué)得在使用之前最好先調(diào)用empty()函數(shù)判斷l(xiāng)ist是否為空。
--------------------------------------------------------------------------------
2.8 pop_back和pop_front():通過(guò)刪除最后一個(gè)元素,通過(guò)pop_front()刪除第一個(gè)元素;序列必須不為空,如果當(dāng)list為空的時(shí)候調(diào)用pop_back()和pop_front()會(huì)使程序崩掉。
--------------------------------------------------------------------------------
2.9 assign():具體和vector中的操作類似,也是有兩種情況,第一種是:l1.assign(n,val)將 l1中元素變?yōu)閚個(gè)T(val)。第二種情況是:l1.assign(l2.begin(),l2.end())將l2中的從l2.begin()到l2.end()之間的數(shù)值賦值給l1。
--------------------------------------------------------------------------------
2.10 swap():交換兩個(gè)鏈表(兩個(gè)重載),一個(gè)是l1.swap(l2); 另外一個(gè)是swap(l1,l2),都可能完成連個(gè)鏈表的交換。
--------------------------------------------------------------------------------
2.11 reverse():通過(guò)reverse()完成list的逆置。
--------------------------------------------------------------------------------
2.12 merge():合并兩個(gè)鏈表并使之默認(rèn)升序(也可改),l1.merge(l2,greater<int>()); 調(diào)用結(jié)束后l2變?yōu)榭?,l1中元素包含原來(lái)l1 和 l2中的元素,并且排好序,升序。其實(shí)默認(rèn)是升序,greater<int>()可以省略,另外greater<int>()是可以變的,也可以不按升序排列。
看一下下面的程序:
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<int> l1;
list<int> l2(2,0);
list<int>::iterator iter;
l1.push_back(1);
l1.push_back(2);
l2.push_back(3);
l1.merge(l2,greater<int>());//合并后升序排列,實(shí)際上默認(rèn)就是升序
for(iter = l1.begin() ; iter != l1.end() ; iter++)
{
cout<<*iter<<" ";
}
cout<<endl<<endl;
if(l2.empty())
{
cout<<"l2 變?yōu)榭???!";
}
cout<<endl<<endl;
return 0;
}
運(yùn)行結(jié)果:

2.13 insert():在指定位置插入一個(gè)或多個(gè)元素(三個(gè)重載):
l1.insert(l1.begin(),100); 在l1的開(kāi)始位置插入100。
l1.insert(l1.begin(),2,200); 在l1的開(kāi)始位置插入2個(gè)100。
l1.insert(l1.begin(),l2.begin(),l2.end());在l1的開(kāi)始位置插入l2的從開(kāi)始到結(jié)束的所有位置的元素。
--------------------------------------------------------------------------------
2.14 erase():刪除一個(gè)元素或一個(gè)區(qū)域的元素(兩個(gè)重載)
l1.erase(l1.begin()); 將l1的第一個(gè)元素刪除。
l1.erase(l1.begin(),l1.end()); 將l1的從begin()到end()之間的元素刪除。
相關(guān)文章
C++實(shí)現(xiàn)LeetCode(45.跳躍游戲之二)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(45.跳躍游戲之二),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C語(yǔ)言中循環(huán)語(yǔ)句練習(xí)實(shí)例
大家好,本篇文章主要講的是C語(yǔ)言中循環(huán)語(yǔ)句練習(xí)實(shí)例,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-01-01
淺談C++中對(duì)象的復(fù)制與對(duì)象之間的相互賦值
這篇文章主要介紹了淺談C++中對(duì)象的復(fù)制與對(duì)象之間的相互賦值,是C語(yǔ)言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09
C語(yǔ)言實(shí)現(xiàn)學(xué)生選課系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)學(xué)生選課系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02
C語(yǔ)言字符串旋轉(zhuǎn)問(wèn)題的深入講解
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言字符串旋轉(zhuǎn)問(wèn)題的相關(guān)資料,文中給出了詳細(xì)的實(shí)現(xiàn)方法,并對(duì)每種方法進(jìn)行了分析和示例代碼,需要的朋友可以參考下2021-09-09
C++異步數(shù)據(jù)交換實(shí)現(xiàn)方法介紹
這篇文章主要介紹了C++異步數(shù)據(jù)交換實(shí)現(xiàn)方法,異步數(shù)據(jù)交換,除了阻塞函數(shù) send() 和 recv() 之外,Boost.MPI 還支持與成員函數(shù) isend() 和 irecv() 的異步數(shù)據(jù)交換2022-11-11

