天天看點

背景開發:核心技術與應用實踐3.3.2 vector的查增删

<b>3.3.2 vector的查增删</b>

<b></b>

<b>1.?vector的初始化和周遊</b>

vector的初始化方法如表3-1所示。

表3-1 vector的各種初始化方法

vector&lt;t&gt;

v1    v1是一個空vector,它潛在的元素是t類型的,執行預設初始化

v2(v1)    v2中包含有v1所有元素的副本

v2 = v1  等價于v2(v1),v2中包含有v1所有元素的副本

v3(n, val)     v3包含了n個重複的元素,每個元素的值都是val

v4(n)     v4包含了n個重複地執行了值初始化的對象

v5{a,b,c...}  v5包含了初始值個數的元素,每個元素被賦予相應的初始值

v5={a,b,c...}      等價于v5{a,b,c...}

vector的周遊有for(int i=0;i&lt;a.size();++i)、for

(iter=ivector.begin();iter!=ivector.end();iter++)、for_each這幾種方式。

【例3.8】 vector的初始化和周遊。

#include

&lt;vector&gt;

&lt;iostream&gt;

using namespace

std;

int main(){

    int a[7]={1,2,3,4,5,6,7};

    vector&lt;int&gt; ivector(a,a+7);

    /*vector的指派并不可以像數組一樣用花括号友善地完成指派,這裡借用了數組來初始化這個vector

      初始化方式vector&lt;elementtype&gt; intvec(begin,end);這樣可以用起來看上去還是比較習慣的。*/

    vector&lt;int&gt;::iterator iter;

    for

(iter=ivector.begin();iter!=ivector.end();iter++){

        cout&lt;&lt;*iter&lt;&lt;" ";

    }

cout&lt;&lt;endl;

    ivector[5]=1;

    /*單個vector的指派,這個方式看上去還是和數組一樣的也可以這麼寫ivector.at(5)=1;但是

      就是不習慣*/

cout&lt;&lt;ivector[5]&lt;&lt;endl&lt;&lt;ivector.size()&lt;&lt;endl;

    cout&lt;&lt;endl;

    for(int i=0;i&lt;5;i++){

        cout&lt;&lt;ivector[i]&lt;&lt;"

";

    return 0;

}

程式的執行結果是:

1 2 3 4 5 6 7

1

7

1 2 3 4 5 1 7

1 2 3 4 5

例3.8中展示了for(int

i=0;i&lt;a.size();++i)、for (iter=ivector.begin();iter!=ivector.end();iter++)的周遊方式,vector中也可以直接用ivector[i]的方式通路第i個元素。

【例3.9】 for_each的周遊舉例。

&lt;algorithm&gt;

void print(int

n)

{

    cout&lt;&lt;n&lt;&lt;" ";

for_each(ivector.begin(),ivector.end(),print);// 用for_each進行周遊

程式的執行結果為:

例3.9中展示了如何使用for_each周遊vector中的元素。

vector是個模闆類,可以存放任何類型的對象。在vector中存放結構體時,可以按照自定義的排序方式排序。

【例3.10】 vector中存放結構體時的排序。

#include&lt;algorithm&gt;

#include&lt;vector&gt;

#include&lt;iostream&gt;

typedef struct

rect{

    int id;

    int length;

    int width;

    bool operator&lt; (const rect &amp;a)

const{

        if(id!=a.id)

            return id&lt;a.id;

        else{

            if(length!=a.length)

                return length&lt;a.length;

            else

                return width&lt;a.width;

        }

}rect;

    vector&lt;rect&gt; vec;

    rect rect;

    rect.id=2;

    rect.length=3;

    rect.width=4;

    vec.push_back(rect);

    rect.id=1;

    rect.length=2;

    rect.width=3;

    vector&lt;rect&gt;::iterator

it=vec.begin();

    cout&lt;&lt;(*it).id&lt;&lt;'

'&lt;&lt;(*it).length&lt;&lt;' '&lt;&lt;(*it).width&lt;&lt;endl;

    sort(vec.begin(),vec.end());

2 3 4

1 2 3

例3.10中,vec中存放的是結構體rect。vec未進行排序前,将會按照push_back的時間順序排序,并不會自動排序。排序後,可以按照結構體中對rect的重載方式進行排序:按照id、length、width升序排序,然後用&lt;algorithm&gt;中的sort函數排序。

除了重載結構體裡的rect,也可以在結構體外定義一個函數來進行比較。

【例3.11】 結構體外定義比較函數。

int cmp(rect

a,rect b){

    if(a.id!=b.id)

                return a.id&lt;b.id;

    else{

                if(a.length!=b.length)

            return a.length&lt;b.length;

        else

            return a.width&lt;b.width;

    sort(vec.begin(),vec.end(),cmp);

例3.11與例3.10不同的地方是,例3.11中并沒有對結構體進行重載,而是在結構體外定義了一個比較函數;另外sort的調用方式也不相同,例3.11中加了個比較函數作為第3個參數。二者均可以實作對vec的排序。

2.?vector的查找

在vector中查找一個元素可以如例3.12所示。

【例3.12】 在vector中查找元素。

    vector&lt;int&gt; vec;

    vec.push_back(1);

    vec.push_back(2);

    vec.push_back(3);

    vec.push_back(4);

    vec.push_back(5);

    vector&lt;int&gt;::iterator

iter=find(vec.begin(),vec.end(),3);

    if ( iter==vec.end())

        cout &lt;&lt; "not found"

&lt;&lt; endl;

    else

        cout &lt;&lt; "found"

found

例3.12中,使用了f?ind函數在vector中進行查找。注意f?ind函數不屬于vector的成員,而存在于算法中,是以應加上頭檔案#include &lt;algorithm&gt;。

3.?vector的删除

vector中的删除,可以有erase或pop_back函數。erase可以删除指定元素或指定位置的元素,而pop_back隻能去掉數組的最後一個資料。

erase的函數原型有以下兩種形式:

iterator

erase(iterator position)。

erase(iterator first, iterator last)。

假設有這樣的程式:

vector&lt;int&gt;

vec;

vec.push_back(1);

vec.push_back(2);

vec.push_back(3);

vec.push_back(4);

vec.push_back(5);

for(vector&lt;int&gt;::iterator

iter=veci.begin(); iter!=veci.end(); iter++){

    if( *iter == 3)

        veci.erase(iter);

乍一看這段代碼很正常,其實這裡面隐藏着一個很嚴重的錯誤:當veci.erase(iter)語句執行了之後,iter就變成了一個野指針,對一個野指針進行iter++操作是肯定會出錯的。

檢視msdn,對于erase的傳回值是這樣描述的:an iterator that designates the

f?irst element remaining beyond any elements removed, or a pointer to the end

of the vector if no such element exists,于是改代碼:

iter=vec.begin(); iter!=vec.end(); iter++){

        iter = vec.erase(iter);

這段代碼也是錯誤的:①無法删除兩個連續的3;②當數字3位于vector最後位置的時候,也會出錯(在vec.end()上執行++操作)。正确的代碼應如例3.13所示。

【例3.13】 使用erase删除vector中某個元素。

iter=vec.begin();

    for(;iter!=vec.end();){

        if(*iter==3){

            iter=vec.erase(iter);

        }else{

            ++iter;

for(iter=vec.begin();iter!=vec.end();iter++){

                cout&lt;&lt;*iter&lt;&lt;"

1 2 4 5

例3.13中,for語句條件裡面删除元素時,傳回值指向已删除元素的下一個位置,不是删除元素時則直接進行++操作。

使用vec.erase(vec.begin()+i,vec.end()+j)語句則是删除區間[i,j-1]間的元素。

而pop_back隻能去掉數組的最後一個資料。

【例3.14】 vector的pop_back函數使用舉例。

    for(int i=0;i&lt;10;i++)

        vec.push_back(i);

    vec.pop_back();

    cout&lt;&lt;endl;     

0 1 2 3 4 5 6 7

8 9

8

例3.14中定義了一個存放整型數的vector,裡面存放了0~9。用pop_back函數,則把最晚進入vector的9删除。

4.?vector的增加

vector中的增加,可以有insert和push_back。insert是插入元素到某個位置中,push_back是在最後添加一個元素。

insert的函數原型有以下3種形式:

iterator insert(

iterator loc, const type &amp;val );

           // 在指定位置loc前插入值為val的元素,傳回指向這個元素的疊代器

void insert(

iterator loc, size_type num, const type &amp;val );

           // 在指定位置loc前插入num個值為val的元素

iterator loc, input_iterator start, input_iterator end );

           // 在指定位置loc前插入區間[start, end)的所有元素

【例3.15】 vector的查增删用法舉例。

void print(

vector&lt;int&gt;v ){

    vector&lt;int&gt;::iterator iter=v.begin();

    for(;iter!=v.end();iter++)

    vector&lt;int&gt; v;              // 現在容器中有0個元素

    int values[] = {1,3,5,7};

    v.insert(v.end(), values+1, values+3);     // 現在容器中有2個元素分别為:3,5

    print(v);

    v.push_back(9);            // 現在容器中有3個元素分别為:3,5,9

    v.erase(v.begin()+1);                // 現在容器中有2個元素分别為:3,9

    v.insert(v.begin()+1, 4);      // 現在容器中有3個元素分别為:3,4,9

    v.insert(v.end()-1, 4, 6);      // 現在容器中有7個元素分别為:3,4,6,6,6,6,9

    v.erase(v.begin()+1, v.begin()+3);   // 現在容器中有5個元素分别為:3,6,6,6,9

    v.pop_back();                    // 現在容器中有4個元素分别為:3,6,6,6

    v.clear();                     //

現在容器中有0個元素

    if (true == v.empty())         // 如果容器為空則輸出“null”

    {

std::cout&lt;&lt;"null"&lt;&lt;std::endl;

例3.15的程式的執行結果如圖3-1所示。

例3.15中的語句:

v.insert(v.end(),

values+1, values+3);

就是将數組第2個元素和第3個元素的值插入到v.end()位置中,因為此時v還是空的,是以也就是往空vector裡插入了兩個元素。注意,這裡隻插入了兩個元素,而沒有插入3個元素。

v.erase(v.begin()+1);

v.begin()是指第1個元素,那v.begin()+1就是指第2個元素,即這裡是删除第2個元素。

v.insert(v.end()-1,

4, 6);

v.end()是指最後一個元素的下一個位置,v.end()-1就是倒數第2個元素的前面一個位置,插入4個6,是以結果是3 4 6 6 6 6 9。

程式中v.clear()表示将v清空;v.empty()表示判斷vector是否為空,如果為空,則傳回true。

繼續閱讀