C++ vector、list用法總結

常用容器之二—— vector 和 list 。

目錄

vector(向量):

優點

缺點

 resize() 和 reserve() 的區別

1. resize(n)函數:

2. reserve(n)函數:

區別:

初始化

訪問

 賦值

插入

刪除

清空

收縮內存

list(雙向鏈表):

優點

缺點

初始化

基本函數

賦值

合併

刪除 

倒轉(逆序)

排序

交換 

刪除重複元素


vector(向量)

vector是一個能夠存放任意類型的動態數組,只能在尾部進行插入和刪除,其實它的用法和數組一樣,只是它的功能比數組強大。

優點

           1.可以隨機訪問任意一個元素。(和數組一樣)

           2.它是動態數組,動態數組是當內存不夠的時候,它可以自動擴增,而不需要我們人爲地進行擴增。

缺點

          和數組一樣,不能很好的進行插入和刪除操作。

必須加頭文件 #include<vector>

先簡單介紹一下函數 push()、empty()、pop()、size()、capacity()、max_size()。

push_back();  //在向量尾部增加一個元素 

empty();  //判斷向量是否爲空

pop_back();  //刪除向量中最後一個元素

size();  //返回向量中元素的個數

resize();  //設置大小(調整容器的長度)

capacity();  //返回當前向量的容量

max_size();  //返回可允許的元素數量的最大值

其實這些函數的用法與之前我們所學的string和stack、queue裏面的用法是一樣的 ,特別是capacity()和resize()函數。

具體請參照之前 string 的博客。
 

reserve();  //設置容量(調整容器的容量大小)

在這裏主要區分一下 resize() 和 reserve() 函數。

1. resize(n)函數

                           resize(n):調整容器的長度大小,使其能容納n個元素

                                             如果n小於當前的size,則刪除多出來的元素,反之,不夠的用值初始化元素的默認值來填充。

                           resize(n,t):這是對於n大於當前的size的情況時,就將新增加的元素都初始化爲t(即用t來填充)。

2. reserve(n)函數

                           reserve(n):預分配n個元素的存儲空間。

                                               如果n小於或者等於capacity,其容量就不會變,反之,就重新分配內存空間,從而使capacity=n。

簡單點說,就是 resize()函數與容器的size有關,而reserve()函數與容器的capacity有關

區別

調用resize()函數後,所有的空間都已經初始化了,所以可以直接訪問;而reserve()函數預分配出的空間沒有被初始化,所以不可訪問。

可以看到,最開始增加元素數量爲10時,而此時容量16比10大,這是因爲計算機認爲你可能還要再增加元素,所以就多開闢了一些空間。 

另外還有一些函數,front()、back()。

front();  //返回首元素

back();  //返回尾元素

以上函數就不再細說了,在下面的代碼中都會經常用到。 

初始化

//Vector<類型>標識符

vector<int>v;  //創建一個空的 vector

 

//Vector<類型>標識符(最大容量)

vector(int n);  //創建一個元素個數爲 n 的vector

以上兩種最好還是用第二種形式。

原因:

 

 可以看到,隨着元素個數的增加,容量也由0變爲了1,而我們前面學string的時候就學習過容量capacity()函數的特性,當元素個數超過了容量之後,此時我們就需要創建一個更大容量的數組,然後把數據複製到這個新數組中,這樣會大大降低效率,所以我們儘量不這樣做,相比之下,所以我們還是儘量採取以下形式:(提前爲其分配空間 )

//Vector<類型>標識符(最大容量,初始值)

vector(int n,const t)  //創建一個 vector,元素個數爲n,且值均爲t

//Vector<類型>標識符(begin,begin+n) 

vector<類型>v1();  //先構造容器v1

vector<類型>v(v1.begin(),v1.begin()+n);  //用v1將v初始化

這樣也可以:

用數組對容器進行初始化

總之是可以這樣用的,至於其中的道理,我是這樣來理解記憶的(雖然不一定理解對了,但最起碼能幫助記住):

 

 以上就是初始化的方法。

訪問

直接使用中括號來訪問  //與數組用法一樣

對了,要是想讓它們都輸出在第一行,就這樣寫就好了:

 at();

區別:中括號與at()函數的區別就在於at()能檢測是否越界,具體的我們在學string時都有詳細瞭解過,如果還不明白的話可以去看一下之前的string的博客。

 賦值

插入

insert();

刪除

 erase();

清空

 clear();

收縮內存

swap();

 

可以看到,當我們使用swap來收縮內存的時候,其容量也確實隨之變了。

list(雙向鏈表)

優點

1. 與向量(vector)相比,它可以快速的進行插入和刪除操作。

2. 不使用連續的內存空間就可以隨意的進行動態操作。

缺點

1. 由於它是鏈表,所以它隨機訪問比較慢,相比vector不能使用at()來訪問

2. 相對於 vector 佔用了更多的內存。

必須加頭文件 #include<list>

初始化

它的初始化與向量(vector)的初始化方法基本上是一樣的(也是上面那5種方法)。

基本函數

它的基本函數與上面向量(vector)的大同小異,可以參照上面的。

還有函數:

begin();  //返回指向第一個元素的迭(die)代器

end();  //返回末尾的迭(die)代器

下面來列舉一下不同於以上的函數:

賦值

list assign();  //給list賦值

也可以這樣:

當然鏈表list同以上vector一樣也可以直接將一個鏈表賦值給另一個鏈表,如下:

合併

merge();

刪除 

remove();

倒轉(逆序)

reverse();  //將鏈表list中的元素倒轉 

 

排序

sort(); 

交換 

swap();

刪除重複元素

unique(); //刪除list中重複的元素

 

以上是兩個比較常用的容器vector和list的相關函數以及用法的總結,其實可以把它們兩個看成正好相反的兩個,也是比較有意思的哈哈。

 

 

 

發佈了22 篇原創文章 · 獲贊 26 · 訪問量 8493
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章