C STL常用容器總結之四 鍊錶list

2021-08-21 20:00:16 字數 2941 閱讀 1971

list是每個節點包含前驅指標、後繼指標和資料域三個部分的雙向鍊錶。list不提供隨機訪問,訪問元素需要按順序走到需訪問的元素,時間複雜度為o(n),在list的任何位置上執行插入或刪除操作都非常迅速,只需在list內部調整一下指標。list不僅是乙個雙向鍊錶,而且還是乙個環狀雙向鍊錶。所以它只需要乙個指標,便可以完整實現整個鍊錶。(這裡需要特別強調一下:list到底是不是雙向鍊錶?有的書上說是,有的書上沒說,所以大家注意一下,這裡暫把list當作雙向鍊錶,等博主找到資料再做解釋) 

與向量vector相比,list允許快速的插入和刪除,且每次插入或刪除乙個元素,就配置或釋放乙個元素空間,對於任何位置的元素插入或元素移除,list永遠是常數時間。 

list不再能夠像vector那樣以普通指標作為迭代器,因為其節點不保證在儲存空間中連續存在。list迭代器必須有能力指向list的節點,並有能力進行正確的遞增、遞減、取值、成員訪問等操作。所謂list迭代器正確的遞增、遞減、取值、成員取用操作是指,遞增時指向下乙個節點,遞減時指向上乙個節點,取值時取的是節點的資料值,成員取用時取用的是節點的成員。 

list有乙個重要性質:插入操作(insert)和合併操作(splice)都不會造成原有的list迭代器失效。這在vector是不成立的,因為vector的插入操作可能造成記憶體重新配置,導致原有的迭代器全部失效。甚至list的元素刪除操作(erase)也只有「指向被刪除元素」的那個迭代器失效,其他迭代器不受任何影響。 

在使用list類模版時,也必須包含相應的標頭檔案:#include,list物件的宣告與vector類似,這裡僅僅介紹一下list的成員函式。

list list1; // 宣告乙個空的list1

list list2 (4, 100); // 宣告以個含4個100的list2

list list3 (list2.begin(), list2.end()); // 用list2的迭代器內容宣告list3

list list4 (list3); // 宣告list4為list3的乙個副本

list list5(size); // 宣告乙個含size個預設值為0的list5

list1.~list(); // 登出list

list與vector相同的一些操作,這裡僅列出函式名,不再進行具體說明:begin/end/rbegin/rend/empty/size/max_size/resize/insert/erase/swap/clear。 

以下這些函式是list與vector不同的函式:

listlist1;
list1.front():返回第乙個元素的值。

list1.back():返回最後乙個元素的值。

list1.push_front(x):把元素x插入到鍊錶頭部。

list1.pop_front():刪除第乙個元素。

list1.push_back(x):把元素x插入到鍊錶尾部。

list1.pop_back():刪除最後乙個元素。

list1.remove(val):刪除鍊錶中所有值為val的元素。

list1.remove_if(pred):刪除鍊錶中謂詞pred為真的元素(謂詞即為元素儲存和檢索的描述,如std::less<>,std::greater<>那麼就按降序/公升序排列,你也可以定義自己的謂詞)。

list1.unique(pred):根據謂詞pred刪除所有重複的元素,使煉表中沒有重複元素。

splice():鍊錶拼接,引數position是迭代器而不是下標。

list1.splice ( position, list2 ):將list2中的所有元素插入到list1中position處,list2會被清空,position仍然指向list1中的那個元素。

list1.splice ( position, list2, iter ):將list2中iter處的元素插入到list1中position處,list2會將iter指向的元素刪除,iter失效。

list1.splice ( position, list2, first, last ):將list2中[first,last)位置處的元素插入到list1的position處。

merge(listref):鍊錶合併:把listref所引用的鍊錶中的所有元素插入到鍊錶中,可指定合併規則。

outputiterator merge (inputiterator1 first1, inputiterator1 last1, inputiterator2 first2, inputiterator2 last2, outputiterator result);

outputiterator merge (inputiterator1 first1, inputiterator1 last1, inputiterator2 first2, inputiterator2 last2, outputiterator result, compare comp); // 由於引數複雜,這裡列出了c++官網給出的原函式,具體的例子可以參考c++官網.

sort():根據預設的謂詞對鍊錶排序,預設公升序。

sort(pred):根據給定的謂詞對鍊錶排序。

c++標準庫中,容器vector和list都可以用來存放一組型別相同的資料。而且二者不同於陣列的一點是,支援動態增長。但它們還是有幾點不同: 

1. vector是順序表,表示的是一塊連續的記憶體,元素被順序儲存;list是雙向鍊錶,在記憶體中不一定連續。 

2. 當數值記憶體不夠時,vector會重新申請一塊足夠大的連續記憶體,把原來的資料拷貝到新的記憶體裡面,再釋放舊空間;list因為不用考慮記憶體的連續,因此新增開銷比vector小。 

3. list只能通過指標訪問元素,隨機訪問元素的效率特別低,在需要頻繁隨機訪問元素時,使用vector更加合適。 

4. 當向vector插入或者刪除乙個元素時,需要複製移動待插入元素右邊的所有元素;因此在有頻繁插入刪除操作時,使用list更加合適。 

5. vector和deque支援隨機訪問,而list不支援隨機訪問,因此list不支援[ ]訪問。

C STL常用容器總結之四 鍊錶list

list是每個節點包含前驅指標 後繼指標和資料域三個部分的雙向鍊錶。list不提供隨機訪問,訪問元素需要按順序走到需訪問的元素,時間複雜度為o n 在list的任何位置上執行插入或刪除操作都非常迅速,只需在list內部調整一下指標。list不僅是乙個雙向鍊錶,而且還是乙個環狀雙向鍊錶。所以它只需要乙...

C STL之list雙向鍊錶容器

不同於採用線性表順序儲存結構的vector和deque容器,list雙向鍊錶中任一位置的元素查詢 插入和刪除,都具有高效的常數階演算法時間複雜度o 1 list技術原理 為了支援前向和反向訪問list容器的元素,list採用雙向迴圈的鍊錶結構組織資料元素,鍊錶的每個節點包括指向前驅的指標 實際資料和...

C STL常用容器總結之八 對映map

map是鍵 值對的集合,map中的所有元素都是pair,可以使用鍵作為下標來獲取乙個值。map中所有元素都會根據元素的值自動被排序,同時擁有實值value和鍵值key,pair的第一元素被視為鍵值,第二元素被視為實值,同時map不允許兩個元素有相同的鍵值。要使用map物件,必須包含map的標頭檔案 ...