list容器用法詳解(超好用的list) c

2021-08-29 03:03:29 字數 3795 閱讀 6959

尊重原創->原創部落格鏈結(吐槽下部落格上**這篇部落格的人不標明出處...找原創找了好久嗚嗚嗚)

1.關於list容器list是一種序列式容器。list容器完成的功能實際上和資料結構中的雙向鍊錶是極其相似的,list中的資料元素是通過鍊錶指標串連成邏輯意義上的線性表,也就是list也具有鍊錶的主要優點,即:在鍊錶的任一位置進行元素的插入、刪除操作都是快速的。list的實現大概是這樣的:list的每個節點有三個域:前驅元素指標域、資料域和後繼元素指標域。前驅元素指標域儲存了前驅元素的首位址;資料域則是本節點的資料;後繼元素指標域則儲存了後繼元素的首位址。其實,list和迴圈鍊錶也有相似的地方,即:頭節點的前驅元素指標域儲存的是鍊錶中尾元素的首位址,list的尾節點的後繼元素指標域則儲存了頭節點的首位址,這樣,list實際上就構成了乙個雙向迴圈鏈。由於list元素節點並不要求在一段連續的記憶體中,顯然在list中是不支援快速隨機訪問的,因此對於迭代器,只能通過「++」或「--」操作將迭代器移動到後繼/前驅節點元素處。而不能對迭代器進行+n或-n的操作,這點,是與vector等不同的地方。

我想把三個常用的序列式放在一起對比一下是有必要的:

vector :vector和built-in陣列類似,擁有一段連續的記憶體空間,能非常好的支援隨即訪問,即操作符,但由於它的記憶體空間是連續的,所以在中間進行插入和刪除會造成記憶體塊的拷貝,另外,當插入較多的元素後,預留記憶體空間可能不夠,需要重新申請一塊足夠大的記憶體並把原來的資料拷貝到新的記憶體空間。這些影響了vector的效率,但是實際上用的最多的還是vector容器,建議大多數時候使用vector效率一般是不錯的。vector的用法解析可以參考本人的另一篇隨筆:

list:list就是資料結構中的雙向鍊錶(根據sgi stl源**),因此它的記憶體空間是不連續的,通過指標來進行資料的訪問,這個特點使得它的隨即訪問變的非常沒有效率,因此它沒有提供操作符的過載。但由於鍊錶的特點,它可以以很好的效率支援任意地方的刪除和插入。

deque:deque是乙個double-ended queue,它的具體實現不太清楚,但知道它具有以下兩個特點:它支援操作符,也就是支援隨即訪問,並且和vector的效率相差無幾,它支援在兩端的操作:push_back,push_front,pop_back,pop_front等,並且在兩端操作上與list的效率也差不多。

因此在實際使用時,如何選擇這三個容器中哪乙個,應根據你的需要而定,具體可以遵循下面的原則

1. 如果你需要高效的隨即訪問,而不在乎插入和刪除的效率,使用vector

2. 如果你需要大量的插入和刪除,而不關心隨即訪問,則應使用list

3. 如果你需要隨即訪問,而且關心兩端資料的插入和刪除,則應使用deque。

2.list中常用的函式

2.1list中的建構函式:

list() 宣告乙個空列表;

list(n) 宣告乙個有n個元素的列表,每個元素都是由其預設建構函式t()構造出來的

list(n,val) 宣告乙個由n個元素的列表,每個元素都是由其複製建構函式t(val)得來的

list(n,val) 宣告乙個和上面一樣的列表

list(first,last) 宣告乙個列表,其元素的初始值**於由區間所指定的序列中的元素

2.2 begin()和end():通過呼叫list容器的成員函式begin()得到乙個指向容器起始位置的iterator,可以呼叫list容器的 end() 函式來得到list末端下一位置,相當於:int a[n]中的第n+1個位置a[n],實際上是不存在的,不能訪問,經常作為迴圈結束判斷結束條件使用。

2.3 push_back() 和push_front():使用list的成員函式push_back和push_front插入乙個元素到list中。其中push_back()從list的末端插入,而 push_front()實現的從list的頭部插入。

2.4 empty():利用empty() 判斷list是否為空。

2.5 resize():如果呼叫resize(n)將list的長度改為只容納n個元素,超出的元素將被刪除,如果需要擴充套件那麼呼叫預設建構函式t()將元素加到list末端。如果呼叫resize(n,val),則擴充套件元素要呼叫建構函式t(val)函式進行元素構造,其餘部分相同。

2.6 clear():清空list中的所有元素。

2.7 front()和back():通過front()可以獲得list容器中的頭部元素,通過back()可以獲得list容器的最後乙個元素。但是有一點要注意,就是list中元素是空的時候,這時候呼叫front()和back()會發生什麼呢?實際上會發生不能正常讀取資料的情況,但是這並不報錯,那我們程式設計序時就要注意了,個人覺得在使用之前最好先呼叫empty()函式判斷list是否為空。

2.8 pop_back和pop_front():通過刪除最後乙個元素,通過pop_front()刪除第乙個元素;序列必須不為空,如果當list為空的時候呼叫pop_back()和pop_front()會使程式崩掉。

2.9 assign():具體和vector中的操作類似,也是有兩種情況,第一種是:l1.assign(n,val)將 l1中元素變為n個t(val)。第二種情況是:l1.assign(l2.begin(),l2.end())將l2中的從l2.begin()到l2.end()之間的數值賦值給l1。

2.10 swap():交換兩個鍊錶(兩個過載),乙個是l1.swap(l2); 另外乙個是swap(l1,l2),都可能完成連個鍊錶的交換。

2.11 reverse():通過reverse()完成list的逆置。

2.12 merge():合併兩個鍊錶並使之預設公升序(也可改),l1.merge(l2,greater()); 呼叫結束後l2變為空,l1中元素包含原來l1 和 l2中的元素,並且排好序,公升序。其實預設是公升序,greater()可以省略,另外greater()是可以變的,也可以不按公升序排列。

看一下下面的程式:

2.13 insert():在指定位置插入乙個或多個元素(三個過載):

l1.insert(l1.begin(),100); 在l1的開始位置插入100。

l1.insert(l1.begin(),2,200); 在l1的開始位置插入2個100。

l1.insert(l1.begin(),l2.begin(),l2.end());在l1的開始位置插入l2的從開始到結束的所有位置的元素。

2.14 erase():刪除乙個元素或乙個區域的元素(兩個過載)

l1.erase(l1.begin()); 將l1的第乙個元素刪除。

l1.erase(l1.begin(),l1.end()); 將l1的從begin()到end()之間的元素刪除。

vector容器用法詳解

vector類稱作向量類,它實現了動態陣列,用於元素數量變化的物件陣列。像陣列一樣,vector類也用從0開始的下標表示元素的位置 但和陣列不同的是,當vector物件建立後,陣列的元素個數會隨著vector物件元素個數的增大和縮小而自動變化。include stdafx.h include inc...

vector容器用法詳解

vector類稱作向量類,它實現了動態陣列,用於元素數量變化的物件陣列。像陣列一樣,vector類也用從0開始的下標表示元素的位置 但和陣列不同的是,當vector物件建立後,陣列的元素個數會隨著vector物件元素個數的增大和縮小而自動變化。include stdafx.h include inc...

C 的vector容器用法

vector是c 標準模板庫中的部分內容,它是乙個多功能的,能夠操作多種資料結構和演算法的模板類和函式庫。vector之所以被認為是乙個容器,是因為它能夠像容器一樣存放各種型別的物件,簡單地說vector是乙個能夠存放任意型別的動態陣列,能夠增加和壓縮資料。為了可以使用vector,必須在你的標頭檔...