關(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ù)組類(lèi)似,擁有一段連續(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中的操作類(lèi)似,也是有兩種情況,第一種是: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與c++之間的相互調(diào)用及函數(shù)區(qū)別示例詳解
這篇文章主要為大家介紹了c與c++相互調(diào)用的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06c++?對(duì)象分配在棧上還是在堆上問(wèn)題分析
這篇文章主要為大家介紹了c++?對(duì)象在棧上還是在堆上問(wèn)題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11C++任意線程通過(guò)hwnd實(shí)現(xiàn)將操作發(fā)送到UI線程執(zhí)行
做Windows界面開(kāi)發(fā)時(shí),經(jīng)常需要在多線程環(huán)境中將操作拋到主線程執(zhí)行,下面我們就來(lái)學(xué)習(xí)一下如何在不需要重新定義消息以及接收消息的情況下實(shí)現(xiàn)這一要求,感興趣的可以了解下2024-03-03C++ 中 <iterator> <functional>&nbs
這篇文章主要介紹了C++ 中 <iterator> <functional> <numeric> 庫(kù)好用的函數(shù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-11-11