<b>3.3.2 vector的查增删</b>
<b></b>
<b>1.?vector的初始化和周遊</b>
vector的初始化方法如表3-1所示。
表3-1 vector的各種初始化方法
vector<t>
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<a.size();++i)、for
(iter=ivector.begin();iter!=ivector.end();iter++)、for_each這幾種方式。
【例3.8】 vector的初始化和周遊。
#include
<vector>
<iostream>
using namespace
std;
int main(){
int a[7]={1,2,3,4,5,6,7};
vector<int> ivector(a,a+7);
/*vector的指派并不可以像數組一樣用花括号友善地完成指派,這裡借用了數組來初始化這個vector
初始化方式vector<elementtype> intvec(begin,end);這樣可以用起來看上去還是比較習慣的。*/
vector<int>::iterator iter;
for
(iter=ivector.begin();iter!=ivector.end();iter++){
cout<<*iter<<" ";
}
cout<<endl;
ivector[5]=1;
/*單個vector的指派,這個方式看上去還是和數組一樣的也可以這麼寫ivector.at(5)=1;但是
就是不習慣*/
cout<<ivector[5]<<endl<<ivector.size()<<endl;
cout<<endl;
for(int i=0;i<5;i++){
cout<<ivector[i]<<"
";
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<a.size();++i)、for (iter=ivector.begin();iter!=ivector.end();iter++)的周遊方式,vector中也可以直接用ivector[i]的方式通路第i個元素。
【例3.9】 for_each的周遊舉例。
<algorithm>
void print(int
n)
{
cout<<n<<" ";
for_each(ivector.begin(),ivector.end(),print);// 用for_each進行周遊
程式的執行結果為:
例3.9中展示了如何使用for_each周遊vector中的元素。
vector是個模闆類,可以存放任何類型的對象。在vector中存放結構體時,可以按照自定義的排序方式排序。
【例3.10】 vector中存放結構體時的排序。
#include<algorithm>
#include<vector>
#include<iostream>
typedef struct
rect{
int id;
int length;
int width;
bool operator< (const rect &a)
const{
if(id!=a.id)
return id<a.id;
else{
if(length!=a.length)
return length<a.length;
else
return width<a.width;
}
}rect;
vector<rect> 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<rect>::iterator
it=vec.begin();
cout<<(*it).id<<'
'<<(*it).length<<' '<<(*it).width<<endl;
sort(vec.begin(),vec.end());
2 3 4
1 2 3
例3.10中,vec中存放的是結構體rect。vec未進行排序前,将會按照push_back的時間順序排序,并不會自動排序。排序後,可以按照結構體中對rect的重載方式進行排序:按照id、length、width升序排序,然後用<algorithm>中的sort函數排序。
除了重載結構體裡的rect,也可以在結構體外定義一個函數來進行比較。
【例3.11】 結構體外定義比較函數。
int cmp(rect
a,rect b){
if(a.id!=b.id)
return a.id<b.id;
else{
if(a.length!=b.length)
return a.length<b.length;
else
return a.width<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<int> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);
vector<int>::iterator
iter=find(vec.begin(),vec.end(),3);
if ( iter==vec.end())
cout << "not found"
<< endl;
else
cout << "found"
found
例3.12中,使用了f?ind函數在vector中進行查找。注意f?ind函數不屬于vector的成員,而存在于算法中,是以應加上頭檔案#include <algorithm>。
3.?vector的删除
vector中的删除,可以有erase或pop_back函數。erase可以删除指定元素或指定位置的元素,而pop_back隻能去掉數組的最後一個資料。
erase的函數原型有以下兩種形式:
iterator
erase(iterator position)。
erase(iterator first, iterator last)。
假設有這樣的程式:
vector<int>
vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);
for(vector<int>::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<<*iter<<"
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<10;i++)
vec.push_back(i);
vec.pop_back();
cout<<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 &val );
// 在指定位置loc前插入值為val的元素,傳回指向這個元素的疊代器
void insert(
iterator loc, size_type num, const type &val );
// 在指定位置loc前插入num個值為val的元素
iterator loc, input_iterator start, input_iterator end );
// 在指定位置loc前插入區間[start, end)的所有元素
【例3.15】 vector的查增删用法舉例。
void print(
vector<int>v ){
vector<int>::iterator iter=v.begin();
for(;iter!=v.end();iter++)
vector<int> 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<<"null"<<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。