您好,登錄后才能下訂單哦!
今天小編給大家分享一下C++之list容器如何使用的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來(lái)了解一下吧。
list底層是帶頭節(jié)點(diǎn)的雙向循環(huán)鏈表
雙向:可以從前往后,也可以從后往前遍歷
循環(huán):找尾節(jié)點(diǎn)的時(shí)間復(fù)雜度為O( 1 )
帶頭節(jié)點(diǎn):代碼實(shí)現(xiàn)簡(jiǎn)單,不用考慮鏈表為空等特殊情況,可令end()迭代器指向頭節(jié)點(diǎn)的位置
list<int> l1; list<int> l2(5, 3); //迭代器 vector<int> v{ 1,2,3,4,5 }; list<int> l3(v.begin(), v.end()); //C++11 list<int> l4{ 1,2,3,4,5 };
利用l1拷貝構(gòu)造l2
list<int> l1{ 1,2,3,4,5 }; list<int> l2(l1);
list<int> l1{ 1,2,3,4,5 }; cout << l1.front() << endl; cout << l1.back() << endl;
list<int> l1{ 1,2,3,4,5 };
采用下面三種方式對(duì)下面這個(gè)list<int>類型的對(duì)象進(jìn)行遍歷打印:
1.迭代器
list<int>::iterator it = l1.begin(); for (it; it != l1.end(); it++) { cout << *it << " "; } cout << endl;
打印結(jié)果:
2.范圍for
注意這里e是int類型,不用再進(jìn)行解引用
//范圍for for (auto e : l1) { cout << e << " "; } cout << endl;
打印結(jié)果:
3.反向迭代器
list<int>::reverse_iterator rit = l1.rbegin(); for (rit; rit != l1.rend(); rit++) { cout << *rit << " "; } cout << endl;
打印結(jié)果:
list支持任意位置的插入,注意list對(duì)象的迭代器不支持加減數(shù)字,因?yàn)槠涞讓涌臻g不連續(xù),如圖:
如果要往一個(gè)位置進(jìn)行插入,可以通過(guò)find函數(shù)返回位置進(jìn)行,find是一個(gè)通用的函數(shù)模板,返回值是傳入?yún)?shù)的迭代器類型,
list<int> l1{ 1,2,3,4,5 }; l1.insert(find(l1.begin(), l1.end(), 3), 10);//任意位置插入 l1.erase(find(l1.begin(), l1.end(), 10), l1.end());//任意位置的刪除
list內(nèi)置的交換函數(shù)
list<int> l1{ 1,2,3,4,5 }; list<int> l2{ 5,6,7,8,9 }; l1.swap(l2);
resize改變有效元素的個(gè)數(shù),多的元素用第resize二個(gè)參數(shù)填充,如果沒(méi)有給第二個(gè)參數(shù),則默認(rèn)用T()。
list<int> l1{ 0,1,2 }; l1.resize(5, 3);
刪除值為value的元素
list<int> l1{ 3,0,1,3,2,3 }; l1.remove(3);
remove_if的參數(shù)是一個(gè)判斷條件,可以是函數(shù)指針或者函數(shù)對(duì)象
//判斷5的倍數(shù) bool MultipleFive(int n) { return 0 == n % 5; } void Test10() { //此處傳遞函數(shù)指針 list<int> l1{ 10,0,1,3,5,7,20 }; l1.remove_if(MultipleFive); }
unique,去重,刪除所有重復(fù)元素,使用unique之前要先調(diào)用sort進(jìn)行排序,這里的sort是list內(nèi)置的sort,不是標(biāo)準(zhǔn)庫(kù)中的sort
void Test() { list<int> l1{ 1,3,3,5,4,0,2,5,4 }; l1.sort();//默認(rèn)升序 l1.unique();//刪除重復(fù)元素 }
結(jié)果:
對(duì)于sort的使用,還可以自定義函數(shù),并將函數(shù)指針作為參數(shù)傳遞給sort函數(shù)進(jìn)行排序:
對(duì)鏈表進(jìn)行逆置
void Test() { list<int> l1{ 1,3,5,7,9 }; l1.reverse(); }
結(jié)果:
list底層結(jié)構(gòu)為帶頭結(jié)點(diǎn)的雙向循環(huán)鏈表,因此在list中進(jìn)行插入時(shí)是不會(huì)導(dǎo)致list的迭代器失效的,只有在刪除時(shí)才會(huì)失效,并且失效的只是指向被刪除節(jié)點(diǎn)的迭代器,其他迭代器不會(huì)受到影響。
erase導(dǎo)致的迭代器失效
如圖所示,it迭代器所指向的位置被刪除后,迭代器失效:
改正方法:
while (it != l1.end()) { //it=l1.erase(it); l1.erase(it++); }
這里 l1.erase(it++)語(yǔ)句也能達(dá)到效果,因?yàn)楹笾?+會(huì)將自增后的結(jié)果保存在臨時(shí)變量中,而前置則不可以。
resize導(dǎo)致的迭代器失效
resize減少有效元素個(gè)數(shù)也會(huì)導(dǎo)致迭代器失效:
list<int> l1{ 1,3,5,7,9 }; auto it = l1.end(); l1.resize(3);
上面這個(gè)程序中,reseze減少有效元素個(gè)數(shù)后,it指向的位置元素已經(jīng)被刪除,迭代器失效,如果再使用該迭代器,則會(huì)出錯(cuò)。
vector(動(dòng)態(tài)順序表)
list(帶頭結(jié)點(diǎn)的雙向循環(huán)鏈表)
對(duì)比 | vector | list |
---|---|---|
底層結(jié)構(gòu) | 動(dòng)態(tài)順序表,連續(xù)空間 | 帶頭結(jié)點(diǎn)的雙向循環(huán)鏈表 |
訪問(wèn) | 支持隨機(jī)訪問(wèn),首地址+下標(biāo) | 不能隨機(jī)訪問(wèn),可通過(guò)find查找,訪問(wèn)隨即元素時(shí)間復(fù)雜度O(N) |
插入刪除 | 任意位置插入和刪除效率低,需要搬移元素,時(shí)間復(fù)雜度為O(N),插入時(shí)有可能需要增容,增容:開(kāi)辟新空間,拷貝元素,釋放舊空間,導(dǎo)致效率更低 | 任意位置插入和刪除效率高,不需要搬移元素,時(shí)間復(fù)雜度為O(1) |
空間利用率 | 底層為連續(xù)空間,不容易造成內(nèi)存碎片,空間利用率較高,緩存利用率高。可以一次將一個(gè)數(shù)據(jù)附近的空間都加載到緩存,不用頻繁地從內(nèi)存讀取數(shù)據(jù) | 底層節(jié)點(diǎn)動(dòng)態(tài)開(kāi)辟,容易造成內(nèi)存碎片,空間利用率低,緩存利用率低 |
迭代器 | 原生態(tài)指針 | 對(duì)指針進(jìn)行了封裝 |
迭代器失效 | 容量相關(guān)的操作都有可能導(dǎo)致迭代器失效,如插入引起的擴(kuò)容,刪除元素等 | 插入元素不會(huì)導(dǎo)致迭代器失效,刪除節(jié)點(diǎn)會(huì)導(dǎo)致,且只影響當(dāng)前迭代器,其他迭代器不受影響 |
使用場(chǎng)景 | 不關(guān)心插入和刪除效率,支持隨機(jī)訪問(wèn) | 大量插入和刪除操作,不關(guān)心隨機(jī)訪問(wèn)的場(chǎng)景 |
以上就是“C++之list容器如何使用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。