vector(向量)
- vector实际上就是对动态数组的封装
- 可以先数组一样可以使用下标访问元素,若vector长度为n,则其下标为0~n-1
- 根据下标访问元素效率更高
- vector对象的空间随着插入删除操作自动调整
- 因为空间自动调整比较耗时,因此频繁的插入删除回事vector的效率下降
一.vector上的基本操作
1.vector对象创建
创建一个空向量
vector<int> v1; //int类型向量
vector<string> s1; //string类型向量
从已有向量复制创建向量
vector<int> v2(v1); //拷贝v1内容到v2(类比于拷贝构造函数)
创建10个元素的向量
vector<string> s2(10);
创建10个元素的向量,所有元素都为1.5
vector<double> v3(10,1.5);
创建向量指针
vector<int> *prec = new vector<int>(10,-5);
2.vector尾部添加元素
使用push_back()函数向vector尾部添加元素
#include<iostream>
#include<vector> //使用vector必备
using namepace std;
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
return 0;
}
3.vector任意位置插入元素
使用insert()函数向vector添加元素
#include<iostream>
#include<vector> //使用vector必备
using namepace std;
int main()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.insert(v1.begin(),0); //头部插入
v1.insert(v1.end(),4); //尾部插入
v1.insert(v1.end()-1,3); //倒数第二位置插入
return 0; //v1.begin(),v1.end()获取相应位置的迭代器
}
4.vector用下标访问元素
#include<iostream>
#include<vector> //使用vector必备
using namepace std;
int main()
{
vector<int> v1;
…… ……
v1.insert(v1.end()-1,3); //倒数第二位置插入
v1[4]=10; //v1[5]=6;越界错误
for(int i=0;i<v1.size();i++) //v1.size(),vector的长度
cout<<v1[i]<<" ";
return 0;
}
5.vector删除尾部元素
使用pop_back()删除
#include<iostream>
#include<vector> //使用vector必备
using namepace std;
int main()
{
vector<int> v1;
…… ……
v1[4]=10; //v1[5]=6;越界错误
v1.pop_back(); //删除10
return 0;
}
6.vector删除任意元素
使用erase()删除任意位置元素
#include<iostream>
#include<vector> //使用vector必备
using namepace std;
int main()
{
vector<int> v1;
…… ……
v1[4]=10; //v1[5]=6;越界错误
v1.pop_back(); //删除10
v1.erase(v1.begin()); //删除0
v1.erase(v1.begin(),vi.end()); //全删,也可以使用v1.clear(),全删
return 0;
}
7.向量大小相关函数
v.size() | 返回向量的大小 |
v.max_size() | 返回向量可容纳的最大个数 |
v.empty() | 返回向量时候为空 |
v.resize(n) | 调整向量大小,使其可以容纳n个元素,如果n<v.size(),则删除多出来的元素;否则,添加新元素 |
v.iesize(n,t) | 调整向量的大小,使其可以容纳n个元素,所有新添加的元素初始化为t |
v.capacity() | 获取向量的容量,在分配内存空间之前所能容纳的元素个数 |
二.vector上的迭代器
1.迭代器的基本信息
向量上的迭代器定义、使用
vector<int>::iterator it;
*it = 5;
vector上迭代器支持随机访问:
- 提供读写操作
- 并能在数据中随机移动(前后,跳跃式)
用加、减操作移动迭代器:
it++; ++it; //指向下一元素
it--; --it; //指向前一元素
it + i; //返回指向 it 后面的第i个元素的迭代器
it – i; //返回指向 it 前面的第i个元素的迭代器
用 <, <=, >, >=,==,!= 判断迭代器前后、相等关系:
it1 < it2 // 表示 it1 在 it2 之前
该特性在一部分情况下成立!
2.begin()和end()函数
每种容器都定义了一对命名为begin和end的函数,用于返回 迭代器。如果容器中有元素,由begin返回的迭代器指向第一 个元素
it = v1.begin(); // 指向v1[0]
由 end 返回的迭代器指向vector的末端元素的下一个。通常 称为超出末端迭代器,表明它指向了一个不存在的元素
it = v1.end(); // 指向末端元素的下一个
如果vector为空,begin返回的迭代器不end返回的迭代器相同
看到这里,我们可以发现,其实在所谓的迭代器中,这些许多操作和我们在学习栈、队列等基本数据结构时是类似的,我们可以将两者对比着来学习、理解。
3. 用迭代器读取元素
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> v1;
for(int i=1; i<10; i++)
v1.push_back(i); // 添加1~9
vector<int>::iterator it;
for(it=v1.begin(); it<v1.end(); it++)
if(*it%2==0) cout<<*it<<" ";
return 0;
}
4. 以迭代器为参数的插入删除函数
v.insert(p,t) | 在迭代器p所指向的元素前面插入值为 t 的元素 |
v.insert(p,n,t) | 在迭代器p所指向的元素前面插入n个值为t的新元素 |
v.insert(p,b,e) | 在迭代器p所指向的元素前面插入迭代器b和e标记的范围内的元素 |
v.erase(p) | 删除迭代器p指向的容器中的元素 |
v.erase(b,e) | 删除迭代器b和e所标记范围内的元素 |
通过迭代器进行删除和插入
vector<int> v2(3, 1);
vector<int> v1(4, 0);
v1.insert(v1.begin(), 5); // 在头部插入5
v1.insert(v1.end(), 7 ); // 在尾部插入7
vector<int>::iterator it = v1.begin() + 4; // 在下标为4处插入9
v1.insert(it, 9 );
for(it=v1.begin(); it<v1.end(); ) // 删除偶数元素
{
if(*it%2==0) it=v1.erase(it);
else it++;
}
v2.insert(v2.begin(),v1.begin(),v1.begin()+2); //将v1的一部分拷贝到v2
如果我们仔细观察上面的代码,我们可以发现一个细节:
it=v1.erase(it);
在我们以往的编程过程中,it是会在for循环中自动增加,这是为什么?
如果我们运行以下代码,我们会发现运行出错
vecotr<int>::iterator it = vc.begin();
for( ; it != vc.end(); it++ )
{ if( ***** ) vc.erase(it); }
这主要是因为在vector中,erase()在删除元素后,迭代器it失效,并没有指向下一个元素,而解决的方法如下:
for(it=v1.begin(); it<v1.end(); )
{
if(*******) it=v1.erase(it);
else it++;
}
我们可以这样做的原因主要是因为在C++11标准中,erase() 会返回一个iterator,这个iterator 指向了“当前删除元素的后继元素” 。我们把这个值赋给it,实现了让it指向下一个元素的操作。
三.vector上的应用算法
常用算法包括:排序sort()、查找find()、替换replace()、合并merge()、反序reverse()、统计count()等。
PS:许多算法都是以迭代器为参数。 有的算法返回一个迭代器。
算法主要在头文件<algorithm>和<numetic>中定义
1.find()
形式:find(first,last,val)
first 和 last 这两个参数都是容器的迭代器,它们 给出了容器中的查找区间起点和终点。
这个区间是个左闭右开的区间[first,last),即区间的起 点是位于查找范围之中的,而终点不是
val参数是要查找的元素的值
函数返回值是一个迭代器。如果找到,则该迭代 器指向被找到的元素。如果找不到,则该迭代器指向查找区间终点。
2.sort()
形式:sort(first,last);
first 和 last 这两个参数都 是容器的迭代器,它们给 出了容器中的查找区间起 点和终点
3.merge()
形式:merge(f1,e1,f2,e2,p);
f1、e1、f2、e2、p都是迭代器
将有序序列v1中[f1, e1)和有序序列v2中[f2, e2)合并成有序序列,存入p的前面
4.其他算法示例
replace( first, last, old, new )
作用:将 [ first,last ) 范围内的所有值为old的替换为new
reverse(start, end)
作用:将序列中 [start, end) 范围反转排列顺序
count(start, end, searchValue)
作用:统计[start, end) 范围内等于searchValue的元素个数
accumulate(first, last, init)
作用:将[ first,last )范围内的所有值相加,再加上init后返回