xqn2017

导航

STL中vector的用法

原本以为自己掌握了vector,但其实只是掌握了vector的访问,特别是删除操作返回的是一个迭代器,却容易和Python的remove()直接删除元素混淆,没有理解透彻,因此在这里总结一下vector的基本用法。

vector应该是STL种最常用的容器了,可以当做数组来看待,只不过vector的元素更丰富,不仅仅是数据元素,还可以是结构体

1、vector的创建和初始化

vector <double> v;//创建一个double类型的vector
vector <int> v2(5);//创建一个含有5个元素的int型vector,初始值默认为0
vector <int> v3(4,7);//创建一个含有4个元素的int型vector,初始值都为7

当然也可以通过在尾部添加元素来初始化

vector <double> v;
v.push_back(3.5);
v.push_back(4.9);
v.push_back(1.5);//其中v[0] = 3.5 v[1] = 4.9 v[2] = 1.5

2、vector的元素遍历

vector <double> v;
v.push_back(3.5);
v.push_back(4.9);
v.push_back(1.5);
//下标访问
for(int i = 0; i < v.size();i++)
{
	cout << v[i] << endl;
}
//const迭代器访问
for(vector <double>::const_iterator it = v.begin(); it !=v.end();it++)
{
	cout << *it << endl;
}
//非const迭代器访问
for(vector <double>::iterator it = v.begin(); it !=v.end();it++)
{
	cout << *it << endl;
}
//逆序访问,同样分为const和非const
for(vector <double>::reverse_iterator it = v.rbegin(); it !=v.rend();it++)
{
	cout << *it << endl;
}

说明一下,其中的const和非const迭代器在访问元素时没有区别,只是非const迭代器可以通过*it = value来改变vector元素的值

3、vector的插入操作

v.insert(v.begin()+2,5); //在索引为2(从0开始)的位置插入元素5
v.insert(v.begin(),2,3);//在索引为0的位置插入2个值为3的元素

4、vector的删除

v.erase(v.begin()+i);//删除索引为i的元素
v.erase(vec.begin()+i,vec.end()+j);删除区间[i,j-1];区间从0开始
v.pop_back();//删除尾部元素 v.clear();//删除所有元素

举个例子,删除double类型的vector中与指定值key相等的元素,并统计个数,其实统计个数可以用 int n = count(v.begin(),v.end(),key) 返回的就是个数,count头文件是<alogrithm>

vector <double> v;
v.push_back(3.5);
v.push_back(4.9);
v.push_back(1.5);
v.push_back(3.5);
v.push_back(3.5);
v.push_back(4.9);
v.push_back(3.5);
double key = 3.5;
const double MIN = 0.00000001;
//索引删除
for(int i =0; i<v.size();i++)
{
	if((v[i] - key < MIN) && (v[i] -key > -MIN)) //double类型,需要定义一个精度
	{
		v.erase(v.begin()+i);
		i--;//假设[2,3,4]删除元素3,其索引为2,删除3后,元素4成了索引2对应的值,所以减一
		cnt++;
	}
}
//或者用迭代器删除
for(it = v.begin();it != v.end();)
{
	
	if((*it - key < MIN) && (*it -key > -MIN)) 
	{
		it = v.erase(it); //删除函数返回的是下一个元素的迭代器
		cnt++;
	}
	else
	{
		it++;
	}	

}

//使用算法删除,remove函数后会获取删除key后迭代器的位置,此时位于新序列的结尾,该位置距离原始序列的结尾还差删除的key的个数的距离,因此再earse最后几个空位置
v.erase(remove(v.begin(),v.end(),key),v.end());

  

5、相关的算法

reverse(vec.begin(),vec.end()); //将元素翻转
sort(vec.begin(),vec.end()); //默认升序排列
bool cmp(const int &m, const int &n)
{
	return a > b;
}
sort(vec.begin(),vec.end(),cmp); //根据cmp排序,这里是

6、vector的内存分配

vector其实维护着三个指针

template <typename T>
class vector
{
	...
	private:
	T* first;
	T* last;
	T* end;
};

  由于没法上图片,这里就简单解说一下吧,创建一个vector时,三个指针均指向同一个位置,当用push_back添加元素时,first指向首元素,last指向尾元素,而end则指向vector.capacity,也就是可以容纳的最大元素个数的索引位置,而这个容量是成指数增加的,添加第1个元素,可容纳1个元素,然后添加第2个元素,此时容器大小为2,然后添加第3个元素,此时容器大小会增加2,变为4,而不是3,添加第4个元素时,由于容器大小为4,可容纳,此时容器大小不变,当添加第5个元素时,容器大小就增加到8了,我理解这是一种策略,不然每次添加一个元素,容器都增加一个空间,增加空间实际上是将原来的内存空间拷贝到了另一个内存空间,过度频繁拷贝导致效率低,所以才成指数级增加,尽管这样,但是拷贝还是很多,效率还是挺低的,不过用起来很方便。所以可以理解为first到last之间的元素为vector实际存储的元素,first到end是vector的可用空间大小。

posted on 2018-06-07 20:05  xqn2017  阅读(413)  评论(0编辑  收藏  举报