1. vector是表示可变大小数组的序列容器。
2. vector就像数组一样,也采用连续的存储空间来存储元素。这样我们就可以采用下标来访问vector的元素;但vector又不是数组,它的大小是动态可变的,会被容器自动处理。
3. 与其他动态序列的容器(比如list、deque等),vector访问元素更加高效,在末尾添加/删除元素更加高效(尾删、尾插);对于不在尾部删除或插入数据操作,效率就低一些。
4. STL库里面vector是一个类模版,使用时需要实例化。(比如: vector<int>)
STL库里面构造函数参数有空间适配器(allocator),这里先不了解这一方面的内容(后面再详细学习)。
(constructor)构造函数 | 接口说明 |
---|---|
vector (); (重点) | 无参构造(默认构造) |
vector(size_type n, const value_type& val = value_type()) | 构造并初始化成n个val |
vector (InputIterator first, InputIterator last); | 使用迭代器进行初始化构造 |
vector (const vector& x); (重点) | 拷贝构造 |
void test1()
{
vector<int> v1; //无参构造(默认构造)
vector<int> v2(10, 1); //构造初始化并初始化成10个1
vector<int> v3(v2.begin(), v2.end()); //使用迭代器区间初始化
vector<int> v4(v2); //拷贝构造
}
在string和vector中迭代器并没有广泛使用(可以进行下标访问);但是任何容器中都可以使用迭代器来遍历,通用性比较强。
iterator的使用 | 接口说明 |
---|---|
begin() 和 end() (重点) | begin()获取第一个位置的iterator/const_iterator、end()获取最后一个位置的iterator/const_iterator |
rbegin() 和 rend() (反向迭代器) | rbegin()获取最后一个位置的iterator/const_iterator、rend()获取第一个的iterator/const_iterator |
有了迭代器,我们还可以使用范围for这一个语法糖。
这里为了方便观察,就先使用**push_back()**尾插一些数据。
void test2()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v1.push_back(5);
//正向迭代器
std::vector<int>::iterator it = v1.begin(); //可以使用auto自动识别类型
while (it != v1.end())
{
cout << *it << " ";
it++;
}
cout << endl;
//范围for
for (auto i : v1)
{
cout << i << " ";
}
cout << endl;
//反向迭代器
std::vector<int>::reverse_iterator rit = v1.rbegin(); //可以使用auto自动识别类型
while (rit != v1.rend())
{
cout << *rit << " ";
rit++;
}
cout << endl;
}
容量空间 | 接口说明 |
---|---|
size() | 获取vector中数据个数 |
capacity() | 获取vector中空间容量大小 |
empty() | 判断是否为空 |
resize() (重点) | 改变vector中size并且设置内容 |
reserve() (重点) | 改变vector中的capacity(空间)大小**(扩容)** |
void test3()
{
vector<int> v1(5, 1);
cout << "size: " << v1.size() << endl;
cout << "capacity: " << v1.capacity() << endl;
if (v1.empty())
{
cout << "为空" << endl;
}
else
{
cout << "不为空" << endl;
}
//resize,n比size小
v1.resize(3);
for (auto i : v1)
{
cout << i << " ";
}
cout << endl;
//resize,n比size大(如果比capacity大就扩容)
v1.resize(10, 2);
for (auto i : v1)
{
cout << i << " ";
}
cout << endl;
//reserve扩容
cout << "扩容前capacity: " << v1.capacity() << endl;
v1.reserve(20);
cout << "扩容后capacity: " << v1.capacity() << endl;
}
这里再多算一个operator [] (下标访问)。
增删查改 | 接口说明 |
---|---|
push_back() (重点) | 尾插 |
pop_back() (重点) | 尾删 |
find() | 查找**(这个不在vector容器内,是算法的接口)** |
insert() | 在pos位置之前插入数据val(也可以插入n个数据) |
erase() | 删除pos位置的数据(或者删除一段迭代器区间的数据) |
swap() | 交换两个vector的数据 |
operator [] (重点) | 下标访问 |
void test4()
{
vector<int> v;
//尾插
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
v.push_back(7);
for (auto i : v)
{
cout << i << " ";
}
cout << endl;
//尾删
v.pop_back();
v.pop_back();
for (auto i : v)
{
cout << i << " ";
}
cout << endl;
//find查找
auto f1 = find(v.begin(), v.end(), 3);//find返回的是迭代器
cout << *f1 << endl;
//insert
v.insert(f1, 2, 66);
for (auto i : v)
{
cout << i << " ";
}
cout << endl;
//erase删除一个数据
auto f2 = find(v.begin(), v.end(), 1);
v.erase(f2);
for (auto i : v)
{
cout << i << " ";
}
cout << endl;
//erase删除一段迭代器区间的数据
auto f3 = find(v.begin(), v.end(), 3);
auto f4 = find(v.begin(), v.end(), 5);
v.erase(f3, f4);
for (auto i : v)
{
cout << i << " ";
}
cout << endl;
//swap交换
vector<int> v1(5, 1);
v.swap(v1);
//下标访问
for (int i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
}
这里有一个问题,就是迭代器失效问题;在调用reserve、insert或者erase等方法后,之前的迭代器会失效(如果继续使用会出问题)
**解决方法:**在使用过后,记得重新给迭代器赋值。
136. 只出现一次的数字 - 力扣(LeetCode)
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ret=0;
for(int i=0;i<nums.size();i++)
{
ret^=nums[i];
}
return ret;
}
};
class Solution {
public:
vector<vector<int>> generate(int numRows) {
vector<vector<int>> vv;
vv.resize(numRows);
for (int i = 0; i < numRows; i++) {
// vv[i].resize(i + 1, 0);
// vv[i][0] = vv[i][i] = 1;
vv[i].resize(i + 1, 1);
}
/*for (int i = 0; i < vv.size(); i++) {
for (int j = 0; j < vv[i].size(); j++) {
if (vv[i][j] == 0) {
vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];
}
}
}*/
for (int i = 1; i < vv.size(); i++) {
for (int j = 1; j < vv[i].size() - 1; j++) {
vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];
}
}
return vv;
}
};
17. 电话号码的字母组合 - 力扣(LeetCode)
这个题有一点难度,我们使用多路递归思路,一次递归来解决。
思路
根据输入的数字,找到对于的字符串,然后多路递归,组成不同的字母组合,最后返回vector类型的对象。
以题目给的示例来分析一下:
这样递归,递归到空时(digits中数的取完后),字母组合完成,尾插到vector类对象v当中。
class Solution {
string StrA[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
public:
void Func(string digits, int level, string s, vector<string>& v)
{
if(level==digits.size())
{
if(level)
v.push_back(s);
return;
}
int num=digits[level]-'0';
string str=StrA[num];
for(int i=0;i<str.size();i++)
{
Func(digits,level+1,s+str[i],v);
}
}
vector<string> letterCombinations(string digits) {
vector<string> ret;
Func(digits,0,"",ret);
return ret;
}
};
vector使用就结束了,使用比较简单,(STL容器的使用比较统一)。