1. 程式人生 > >C++/STL_中vector基本操作測試程式碼,vector.erase()使用方法

C++/STL_中vector基本操作測試程式碼,vector.erase()使用方法

通過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;
}