C++/STL_中vector基本操作測試程式碼,vector.erase()使用方法
阿新 • • 發佈:2019-01-03
通過vector我們可以減少類裡的變數,比如一個類裡儲存了一種資料,但是不知道這種資料到底要儲存個,我們常常使用(結構體陣列/物件陣列),加一個變數來表示 記錄的數量。但是通過vector可以簡化這個變數,因為vector裡面有通用的size方法可以幫我們完成這個操作。
vector在尾部進行插入操作是高效的。vector只是簡單地變長來適應新加入的元素。但在vector中間插入或刪除元素是低效的,即在插入或刪除的位置之後的整個部分都需要移動,因為vector在記憶體中佔用的是連續的空間,和C/C++的源生陣列一樣。
測試程式碼:
#include <vector> #include <iostream> using namespace std; struct Point{ int x; int y; }; ostream& operator<<(ostream &output, const Point &a){ return output << a.x << " " << a.y ; } int main(){ vector<Point> PointList; vector<Point>::iterator iter; //a[10] = 5; Point a; a.x = 5; a.y = 5; Point b; b.x = 4; b.y = 4; PointList.push_back(a); PointList.insert(PointList.begin()+1,b); PointList.push_back(a); //PointList._Pop_back_n(2); //delete the last two Points in PointList cout << "traverse the PointList " << endl; for (iter = PointList.begin(); iter != PointList.end(); iter++){ cout << *iter << endl; } cout << "The sizeof vector<Point> PointList is "; cout << PointList.size() << endl; cout << "output the Point which x == 5" << endl; for (iter = PointList.begin(); iter != PointList.end(); iter++){ if ( 5 == (*iter).x ) cout << *iter << endl; } /* cout << "erase all the Points which 5 == x" << endl; for (iter = PointList.begin(); iter != PointList.end(); iter++){ if (5 == (*iter).x) PointList.erase(iter); } cout << "traverse the PointList " << endl; for (iter = PointList.begin(); iter != PointList.end(); iter++){ cout << *iter << endl; } */ cout << endl << "Hello KeMeng~" << endl; return 0; }
容器(vector,deque,list)的刪除操作需要注意,可以通過erase方法刪除滿足條件的資料。但是以下程式碼會出錯:(刪除多個數據)
cout << "erase all the Points which 5 == x" << endl;
for (iter = PointList.begin(); iter != PointList.end(); iter++){
if (5 == (*iter).x)
PointList.erase(iter);
}
原因:
原來是刪除迭代器i後,i所指的元素已經失效了,然後給i++,它已經不在存在了。。。
連結:http://blog.csdn.net/u010003835/article/details/47421467
下面演示一下如何在vector 刪除滿足條件的資料:
//兩種方式
//方式一 : 通過erase的返回值找到下一個元素
for (iter = PointList.begin();iter!=PointList.end();){
if (5 == (*iter).x){
iter = PointList.erase(iter);
}
else
iter++;
}
bool equal_five(const Point & a); //remove_if 需要的判斷函式,remove_if返回滿足刪除條件的起始位置 //方式二 : 通過remove_if來返回邊界再用 erase 刪除 PointList.erase(remove_if(PointList.begin(), PointList.end(), equal_five), PointList.end()); bool equal_five(const Point & a){ return a.x == 5 ? true : false; }
測試輸出
下面再展示 另一種錯誤的程式碼
vector<Point>::iterator next = PointList.begin();
for (iter = PointList.begin(); ; ){
if (PointList.end() == next)
break;
++next;
if (5 == (*iter).x){
PointList.erase(iter);
}
iter = next;
}
然而結果會報錯:
估計與vector實現有關,vector為陣列,刪除後進行前移,儲存之前的位置沒用。
c.end()由於模仿陣列會發生變動。
錯誤程式碼
#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
using namespace std;
struct p{
int x;
int y;
};
ostream& operator<<(ostream &output, const p &a){
return output << a.x << " " << a.y;
}
int main(){
vector<p> c;
p a,b;
a.x = 12;
a.y = 12;
b.x = 13;
b.y = 13;
c.push_back(a);
c.push_back(b);
for (vector<p>::iterator ak = c.begin(); ak != c.end(); ak++){
cout << (*ak) << endl;
}
cout << endl << c[1] << endl;
// todo insert items
vector<p>::iterator nextitr = c.begin();
for (vector<p>::iterator i = c.begin();;)
{
if (nextitr == c.end())
break;
++nextitr;
if ((*i).x>10)
{
// 如果有一個值大於10,刪除之
c.erase(i);
}
i = nextitr;
}
cout << c.size() << endl;
return 0;
}
但是對於list是可行的。 原因:list相當於連結串列
#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
using namespace std;
struct p{
int x;
int y;
};
ostream& operator<<(ostream &output, const p &a){
return output << a.x << " " << a.y;
}
int main(){
list<p> c;
p a,b;
a.x = 12;
a.y = 12;
b.x = 13;
b.y = 13;
c.push_back(a);
c.push_back(b);
for (list<p>::iterator ak = c.begin(); ak != c.end(); ak++){
cout << (*ak) << endl;
}
// todo insert items
list<p>::iterator nextitr = c.begin();
for (list<p>::iterator i = c.begin();;)
{
if (nextitr == c.end())
break;
++nextitr;
if ((*i).x>10)
{
// 如果有一個值大於10,刪除之
c.erase(i);
}
i = nextitr;
}
cout << c.size() << endl;
return 0;
}
另一種更簡便的方式
for (list<p>::iterator i = c.begin(); i!=c.end();)
{
if ((*i).x > 10)
{
// 如果有一個值大於10,刪除之
c.erase(i++);
}
else
i++;
}
另外一種方式
std::list< int> List;
std::list< int>::iterator itList;
for( itList = List.begin(); itList != List.end(); )
{
if( WillDelete( *itList) )
{
itList = List.erase( itList);
}
else
itList++;
}
因此,我想到了是否對list進行下標訪問,以下操作是非法的:
cout << c[1] << endl;
但是該操作對於vector又是可行的,vector相當於陣列,故可以通過下標的形式訪問:
#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
using namespace std;
struct p{
int x;
int y;
};
ostream& operator<<(ostream &output, const p &a){
return output << a.x << " " << a.y;
}
int main(){
vector<p> c;
p a,b;
a.x = 12;
a.y = 12;
b.x = 13;
b.y = 13;
c.push_back(a);
c.push_back(b);
for (vector<p>::iterator ak = c.begin(); ak != c.end(); ak++){
cout << (*ak) << endl;
}
cout << c[1] << endl;
/*
// todo insert items
vector<p>::iterator nextitr = c.begin();
for (vector<p>::iterator i = c.begin();;)
{
if (nextitr == c.end())
break;
++nextitr;
if ((*i).x>10)
{
// 如果有一個值大於10,刪除之
c.erase(i);
}
i = nextitr;
}
*/
cout << c.size() << endl;
return 0;
}