1. vector是表示可变大小数组的序列容器,就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素 进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
原先数组的本质也是对一个个整形进行数据管理,可以想象成一个表格,由于需要管理的数据比起单个整形,现实情况更加的复杂和庞大,因此其作用也需要扩大,可以将其想象成一个笔记本,被开一个空间则表示笔记本有多少页,统一管理一个相同类型的数据,当然如果系统更为复杂的情况,则可以往更大的系统去想象
2.本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是 一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
3.vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存 储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是 对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增 长。与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末 尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起list和forward_list 统一的迭代器和引用更好。
构造函数声明 | 接口说明 |
vector() | 无参构造 |
vector(size_type n, const value_type& val = value_type()) | 构造并初始化n个val |
vector (InputIterator first, InputIterator last) | 用迭代器初始化 |
vector (const vector& x) | 拷贝构造 |
vector first; // empty vector of ints
vector second(4, 100); // four ints with value 100
vector third(second.begin(), second.end()); // iterating through second
vector fourth(third); // a copy of third
iterator的使用 | 接口说明 |
begin+end | begin获取第一个数据位置的iterator,end获取最后一个数据下一个位置的iterator |
rbegin+end | rbegin获取最后一个数据位置的reverse_iterator,end获取第一个数据前一个位置的reserve_iterator |
void PrintVector(const vector& v)
{
// const对象使用const迭代器进行遍历打印
vector::const_iterator it = v.begin();
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
迭代器失效问题
对于vector可能会导致其迭代器失效的操作有:
1. 会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize、reserve、insert、assign、 push_back等。
2. 指定位置元素的删除操作--erase,删除操作在vs编译器认为,一旦执行,则原有迭代器视为失效
3. 与vector类似,string在插入+扩容操作+erase之后,迭代器也会失效。
迭代器失效解决办法:在使用前,对迭代器重新赋值即可。
容量空间 | 接口说明 |
size | 获取数据个数 |
capacity | 获取容量大小 |
empty | 判断是否为空 |
resize |
改变vector的size,必要时会扩容,但不会缩容 |
reserve | 改变vector的capacity的大小,必要是会扩容,一般不缩容 |
增删查改 | 接口说明 |
push_back | 尾插 |
pop_back | 尾删 |
find | 查找(vector接口内没有自带的查找接口,需要时常用算法模块的查找功能),传参传迭代器,找到返回对应迭代器位置,找不到返回end的位置 |
insert | 在pos之前插入val值 |
erase | 删除pos位置的数据 |
swap | 交换两个vector的数据空间 |
operator[ ] | 像数组一样访问 |
void TestVector5()
{
// 使用列表方式初始化,C++11新语法
vector v{ 1, 2, 3, 4 };
// 在指定位置前插入值为val的元素,比如:3之前插入30,如果没有则不插入
// 1. 先使用find查找3所在位置
// 注意:vector没有提供find方法,如果要查找只能使用STL提供的全局find
auto pos = find(v.begin(), v.end(), 3);
if (pos != v.end())
{
// 2. 在pos位置之前插入30
v.insert(pos, 30);
}
vector::iterator it = v.begin();
while (it != v.end())
{
cout << *it << " ";
++it;
}
cout << endl;
pos = find(v.begin(), v.end(), 3);
// 删除pos位置的数据
v.erase(pos);
it = v.begin();
while (it != v.end()) {
cout << *it << " ";
++it;
}
cout << endl;
}
// operator[]+index 和 C++11中vector的新式for+auto的遍历
// vector使用这两种遍历方式是比较便捷的。
题目链接:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
题目描述:
在一组数字中,除了一个数字是单独出现的,其余都是成双出现的,要求找到那个单独的数字。
解题思路:
全部异或一起就能找到那个数字
参考代码:
class Solution {
public:
int singleNumber(vector& nums)
{
int ret = 0;
for(auto ch: nums)
{
ret^=ch;
}
return ret;
}
};
题目链接:
118. 杨辉三角 - 力扣(LeetCode)
题目描述:
给一个数字表示杨辉三角的层级数,需要返回一个类似于二维数组的结构去表示杨辉三角
解题思路:
首先先构造出杨辉三角的结构,可以用vector
代码参考:
class Solution {
public:
vector> generate(int numRows)
{
vector> vvi;
vvi.resize(numRows);
for(int i = 0;i
题目链接:
17. 电话号码的字母组合 - 力扣(LeetCode)
题目描述:
数字“2-9”对应着一串字母,题目给定一串数字字符串,要求得到对应字母的全排列组合
解题思路:
这里画出部分逻辑,将数字先转化成字母串,对字母串每一个都单独往下递归,将递归至最后一层的结果记录下来,最终将所有组合完成递归后结束。
参考代码:
class Solution
{
string num_let[10] = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
public:
//递归的参数设计上,第一个参数是数字字符,第二个di是用于在递归过程中控制字母字符是第几层的参数
//第三个参数是用于在递归过程中记录下每次完成一次排列后的结果,第四个参数则是每次完成单趟排列后,统一存起来,用于返回的
//因此,第一个参数和第四个参数采用的是传引用
void letterCom(string& s_num,int di,string tmp,vector& ret)
{
if(di == s_num.size())//递归的结束条件,结束时将单次排列的结果存到ret中
{
ret.push_back(tmp);
return;
}
//先将每一层对应的字母串取出来
int num = s_num[di] - '0';
string s_letter= num_let[num];
//每一个都逐一向下递归
for(auto ch: s_letter)
{
letterCom(s_num,di+1,tmp+ch,ret);
}
}
vector letterCombinations(string digits)
{
vector ret;//用于存放返回的结果
if(digits == "")//这里是考虑到空数字字符,则直接返回空
{
return ret;
}
letterCom(digits,0,"",ret);//递归的参数不止一个digits,因此要单独用一个函数实现递归
return ret;
}
};
本篇对vector的常用接口进行了整理介绍,并且整理了相关的OJ题,用于练习熟悉vector的使用。