容器vector

vector

vector容器的基本概念
vector的数据安排及操作方式,与array非常相似,两者的唯一区别在于空间的运用的灵活性。array是静态空间,一旦配置了就不能改变,要换大一点或者小一点的空间,可以,一切琐碎得有自己来,首先配置一块新的空间,然后将旧空间的数据搬往新的空间,再释放原来的空间。vector是动态空间,随着元素的加入,它的内部机制会自动扩充空间以容纳新的元素,因此vector的运用对于内存的合理利用与运用的灵活性有很大的帮助,我们再也不比害怕空间不足而一开始就要求一个大块头的array了。
vector的实现技术,关键在于其对大小的控制以及重现配置是的数据移动效率,一旦vector旧空间满了,如果客户每新增一个元素,vector内部只是扩充一个元素的空间,实为不智,因为所谓的扩充空间(不论多大),一如刚所说,是“配置新的空间-移动数据-释放就空间”的大工程,时间成本很高,应该加入某种未雨绸缪的考虑,稍后我们可以看到vector的空间配置策略。
vector迭代器
vector维护一个线性空间,所以不论元素的型别如何,普通指针都可以作为vector的迭代器,因为vector迭代器所需要的操作行为,如operator*,operator->,operator++,operator–,operator+,operator-,operator+=,operator-=,普通指针天生具备,vector支持随机存取,而普通指针正有着这样的能力。所以vector提供的时随机访问迭代器
根据上述描述,如果我们写如下代码:
Vector iterator it1;
Vector iterator it2;
it1的型别其实就是int*,it2的型别其实是teacher*

	//An highlighted block
#include <iostream>
#include <vector>
using namespace std;

int main()
	{
		vector<int> v;
		for(int i = 0;i<10;i++)
			{
				v.push_back(i);
				cout << v.capacity() << endl;		//v.capacity()容器的容量
			}
	
		system("pause");
		return 0;
	}

在这里插入图片描述vector 使用算法来增加容量,这个算法依赖一个经常使用的常对数来实现,这在早些时候会导致分配一些非常小的内存,但是随着 vector 容量的增大,内存增长数也会变大

vector的数据结构
vector所采用的数据结构非常简单,线性连续空间,它以两个迭代器 Myfirst和Mylast分别指向配置得来的连续空间中目前已被使用的范围,并以迭代器Myend指向整块连续内存空间的尾端。
为了降低空间配置时的速度成本,vector实际配置的大小可能比客户端需求大一些,以备将来可能的扩充,这边是容量的概念,换句话说,一个vector的容量永远大于或等于其大小,一旦容量等于大小,便是满载,下次再有新增元素,整个vector容器就得另觅居所。
注意:
所谓动态增加大小,并不是在原来的空间之后连续的接新空间(因为无法保证原空间之后是否有可配置的空间),而是一块更大的内存空间,然后将原数据拷贝新空间,并释放原空间,因此,对vector的任何操作,一旦引起空间的重新配置,指向原vector的所有迭代器都就都失效了。
这是程序员容易犯的一个错误,务必小心

vector常用API操作

vector构造函数
vectorv //采用模板实现类实现,默认构造函数
vector(v.begin(),v.end()) //将v(begin(),end())区间中的元素拷贝给本身
vector(n,elem) //构造函数将n个elem拷贝给本身
vector(); //创建一个空的vector
vector(int nSize) //创建一个vector,元素个数为nSize
vector(int nSize,const t& t) //创建一个vector,元素个数为nSize,且值均为t
vector(const vector&) //复制构造函数

//例子   使用第二个构造函数,我们可以
int arr[] = {1,2,3,4,5,6};
vector<int> v1(arr,arr+sizeof(arr)/sizeof(int));

vector常用赋值操作
assign(beg,end) //将(beg,end)区间的中的数据拷贝赋值给本身
assign(n,elem) //将n个elem拷贝赋值给本身
vector & operator=(const vector &vec) //重载等号操作符
swap(vec) //将vec与本身的元素互换

vector大小操作
size() //返回容器中元素的个数
empty() //判断容器是否为空,若为空,则向量中无元素
resize(int num) //重新指定容器的长度为num,若容器变长,则以默认值填充新位置,如果容器变短,则末尾超出容器长度的元素被删除
resize(int num,elem) //重新指定容器的长度为num,若容器变长,则以elem填充新位置,如果容器变短,则末尾超出容器长度的元素被删除
capacity() //容器的容量
reserve(int len)

 //  vector<double> v;
//   v.reserve(20)
//  这样就设置了容器的内存分配,至少可以容纳 20 个元素。
	如果当前的容量已经大于或等于 20个元素,那么这条语句什么也不做。
    注意,调用 reserve() 并不会生成任何元素。
	values 容器这时仍然没有任何元素,直到添加了 20 个元素后,才会分配更多的内存。
    调用 reserve() 并不会影响现有的元素。
	当然,如果通过调用 reserve() 来增加内存,任何现有的迭代器,
	例如开始迭代器和结束迭代器,都会失效,所以需要重新生成它们。
 这是因为,为了增加容器的容量,vector<T> 容器的元素可能已经被复制或移到了新的内存地址。

常用函数补充
1.构造函数

vector():创建一个空vector
vector(int nSize):创建一个vector,元素个数为nSize
vector(int nSize,const t& t):创建一个vector,元素个数为nSize,且值均为t
vector(const vector&):复制构造函数
vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中

2.增加函数

void push_back(const T& x):向量尾部增加一个元素X
iterator insert(iterator it,const T& x):向量中迭代器指向元素前增加一个元素x
iterator insert(iterator it,int n,const T& x):向量中迭代器指向元素前增加n个相同的元素x
iterator insert(iterator it,const_iterator first,const_iterator last):向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据

3.删除函数

iterator erase(iterator it):删除向量中迭代器指向元素
iterator erase(iterator first,iterator last):删除向量中[first,last)中元素
void pop_back():删除向量中最后一个元素
void clear():清空向量中所有元素

4.遍历函数

reference at(int pos):返回pos位置元素的引用
reference front():返回首元素的引用
reference back():返回尾元素的引用
iterator begin():返回向量头指针,指向第一个元素
iterator end():返回向量尾指针,指向向量最后一个元素的下一个位置
reverse_iterator rbegin():反向迭代器,指向最后一个元素
reverse_iterator rend():反向迭代器,指向第一个元素之前的位置

5.判断函数

bool empty() const:判断向量是否为空,若为空,则向量中无元素

6.大小函数

int size() const:返回向量中元素的个数
int capacity() const:返回当前向量张红所能容纳的最大元素值
int max_size() const:返回最大可允许的vector元素数量值

7.其他函数

void swap(vector&):交换两个同类型向量的数据
void assign(int n,const T& x):设置向量中第n个元素的值为x
void assign(const_iterator first,const_iterator last):向量中[first,last)中元素设置成当前向量元素

8.看着清楚

1.push_back 在数组的最后添加一个数据

2.pop_back 去掉数组的最后一个数据

3.at 得到编号位置的数据

4.begin 得到数组头的指针

5.end 得到数组的最后一个单元+1的指针

6.front 得到数组头的引用

7.back 得到数组的最后一个单元的引用

8.max_size 得到vector最大可以是多大

9.capacity 当前vector分配的大小

10.size 当前使用数据的大小

11.resize 改变当前使用数据的大小,如果它比当前使用的大,者填充默认值

12.reserve 改变当前vecotr所分配空间的大小

13.erase 删除指针指向的数据项

14.clear 清空当前的vector

15.rbegin 将vector反转后的开始指针返回(其实就是原来的end-1)

16.rend 将vector反转构的结束指针返回(其实就是原来的begin-1)

17.empty 判断vector是否为空

18.swap 与另一个vector交换数据
//An highlighted block
void printVector(vector<int> &v)
	{
	for(vector<int>::iterator it = v.begin();it != v.end();it++)
		{
			cout << *it << " ";
		}
		cout << endl;
	}
void test2()
	{
		vector<int> v;
		int arr[] = {2,3,4,5,6};
		vector <int> v1 (arr,arr+sizeof(arr)/sizeof(int));

		vector<int>v2(v1.begin(),v1.end());
		printVector(v2);

		vector<int>v3(10,100);
		printVector(v3);

		//赋值使用
		vector<int>v4;
		v4.assign(v3.begin(),v3.end());
		printVector(v4);


		v4.swap(v2);
		cout << "交换后的v4" << endl;
		printVector(v4);


		cout << "v4容器的大小:" << v4.size() << endl;

		if(v4.empty())
			{
				cout << "v4空" << endl;
			}
		else
			{
				cout << "v4不空" << endl;
			}
		//v4 23456
		v4.resize(10);
		printVector(v4);

		v4.resize(20,-1);		//第二个参数是默认值,默认为0
		printVector(v4);

		v4.resize(3);		
		printVector(v4);
	}

在这里插入图片描述

//An highlighted block
//巧用swap收缩空间
void test3()
	{
		vector<int>v;
		for(int i = 0;i<100000;i++)
			{
			v.push_back(i);
			}
		cout << "v的容量:" << v.capacity() << endl;
		cout << "v的大小:" << v.size() << endl;
	
		v.resize(3);
		cout << "v的容量:" << v.capacity() << endl;
		cout << "v的大小:" << v.size() << endl;

		//巧用swap
		vector<int>(v).swap(v);			//利用对象v初始化匿名的vector对象
		cout << "v的容量:" << v.capacity() << endl;
		cout << "v的大小:" << v.size() << endl;
	}

在这里插入图片描述

//An highlighted block
//reserve(int len)
void test4()
	{
		vector<int>v;
		
		int *p = NULL;
		int num = 0;
		for(int i = 0;i<100000;i++)
			{
			v.push_back(i);
			if(p != &v[0])
				{
					p = &v[0];
					num++;
					cout <<"v的容量为:" << v.capacity() << endl;
				}
			
			}
		cout << "开辟100000用了多少次" << num << endl;
		//开辟100000用了多少次
		vector<int>v2;
		v2.reserve(100000);		//预留出空间
		
		int *p1 = NULL;
		int num1 = 0;
		for(int i = 0;i<100000;i++)
			{
			v2.push_back(i);
			if(p1 != &v2[0])
				{
					p1 = &v2[0];
					num1++;
					cout << "v2的容量:" <<  v2.capacity() << endl;
				}
			
			}
		cout << "开辟100000用了多少次" << num1 << endl;		
	
	}

在这里插入图片描述

//An highlighted block
void printVector(vector<int> &v)
	{
	for(vector<int>::iterator it = v.begin();it != v.end();it++)
		{
			cout << *it << " ";
		}
		cout << endl;
	}
void test5()
	{
		vector<int>v;
		v.push_back(10);
		v.push_back(30);
		v.push_back(45);
		v.push_back(77);
		cout << "v的front:" << v.front() << endl;
		cout << "v的back:" << v.back() << endl;


		v.insert(v.begin(),2,100);
		//参数1  迭代器    参数2 N个数  参数3  具体数
		printVector(v);

		v.pop_back();			//尾删
		printVector(v);

		v.erase(v.begin());		//删除
		printVector(v);
	

		//v.erase(v.begin(),v.end());

		v.clear();		//清空所有数据
		if(v.empty())
			{
				cout << "为空" << endl;
			}
		v.clear();		//清空所有数据
	}

在这里插入图片描述

//An highlighted block

void test6()
	{
		//逆序遍历
		vector<int>v;
		for(int i = 0;i<10;i++)
			{
			v.push_back(i);
			}
		printVector(v);
		//逆序迭代器reverse_iterator
		for(vector<int>::reverse_iterator it = v.rbegin();it != v.rend();it++)
			{
				cout << *it << " " ;
			}
		cout << endl;
	
		//vector迭代器是随机访问的迭代器   支持跳跃式访问
		vector<int>::iterator itBegin = v.begin();
		itBegin = itBegin + 3;
		//如果上述写法不报错,这个迭代器是随机访问迭代器

		list<int>l;
		for(int i = 0;i<10;i++)
			{
			l.push_back(i);
			}
		list<int>::iterator lIt = l.begin();
	//	lIt = lIt + 1;	//不支持随机访问

	}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值