文档介绍
文档介绍
1.vector是表示可变大小数组的容器
2.就像数组一样,vecotr也采用的连续存储空间来存储元素,也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,大小是可以动态改变的,大小会被容器自动处理
3.本质讲,vecotr的使用动态分配数组来存储元素,当新元素插入时,数组需要被重新分配大小,为了增加存储空间,做法是分配一个新的数组,将全部元素移到这个数组,就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小
4.vector分配空间策略,分配一些额外的空间适应可能得增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的是黑色在常数时间的复杂度完成的
5.因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长
6.与其它动态序列容器相比(deque,list and forward_list),vector在访问元素的时候效率更高,末尾添加和删除元素高效,不在末尾,效率更低,比起list和forwar_list统一的迭代器和引用更好
vector的使用
一定要学会查看文档,是非常重要的
定义
constructor 构造函数声明 | 接口说明 |
---|---|
vector() 重点 | 无参构造 |
vector(size_type n, const value_type& val = value_type()) | 构造并初始化n个val |
vector (const vector& x) 重点 | 拷贝构造 |
vector (Inputlterator first, InputIterator last) | 使用迭代器初始化构造 |
InputIterator是可以单向迭代器.是一个模板,可以传任意类型的迭代器,用string的迭代器也没问题
iterator的使用
iterator 的使用 | 接口说明 |
---|---|
begin + end 重点 | 获取第一个数据位置的iterator/const_iterator,获取最后一个数据的下一个位置的iterator/const_iterator |
rbegin + rend | 获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator |
int main()
{
//初始化
//vector()
//vector(size_type n, const value_type& val = value_type())
//vector (InputIterator first, InputIterator last);
vector<int> v1;
vector<int> v2(3, 5);
vector<int> v3(v2.begin(), v2.end());
string s1("hello");
vector<char> v4(s1.begin(), s1.end());
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
/*vector<int>::reverse_iterator rit = v1.rbegin();
while (rit != v1.rend())
{
cout << *rit << endl;
rit++;
}*/
cout << v2.max_size();
for (auto ch : v4)
{
cout << ch << " ";
}
return 0;
}
空间增长
容量空间 | 接口说明 |
---|---|
size | 获取数据个数 |
capacity | 判断容量大小 |
empty | 判断是否为空 |
resize 重点 | 改变vector的size |
reserve 重点 | 改变vector的capacity |
capacity的代码在vs和g++下分别运行会发现,vs下capacity是1.5被增长的,g++是2倍增长的,vs的版本是PJ,g++是SGI版本
reserve只负责开辟空间,如果确定知道需要多少空间,reserve可以缓解vector增容的代价缺陷问题
resize在开辟空间的同时还会初始化,影响size
void test1()
{
vector<int> v1;
size_t size = v1.capacity();
cout << size << endl;
for (size_t i = 0; i < 100; i++)
{
v1.push_back('4');
if (size != v1.capacity())
{
cout << v1.capacity() << endl;
size = v1.capacity();
}
}
}
// 如果已经确定vector中要存储元素大概个数,可以提前将空间设置足够
// 就可以避免边插入边扩容导致效率低下的问题了
void TestVectorExpandOP()
{
vector<int> v;
size_t sz = v.capacity();
v.reserve(100); // 提前将容量设置好,可以避免一遍插入一遍扩容
cout << "making bar grow:\n";
for (int i = 0; i < 100; ++i)
{
v.push_back(i);
if (sz != v.capacity())
{
sz = v.capacity();
cout << "capacity changed: " << sz << '\n';
}
}
}
增删改查
增删改查 | 接口说明 |
---|---|
push_back 重点 | 尾插 |
pop_back 重点 | 尾删 |
find | 查找 这个是算法模块实现,不是vector的成员接口 |
insert | 再position位置前插入val |
erase | 删除position位置的数据 |
swap | 交换两个vector的数据空间 |
operator[] 重点 | 像数组一样访问 |
vector的插入删除必须使用迭代器做参数,不提供下标的删除,为了和其他容器保持一致
void test2()
{
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
//insert需要迭代器参数
vector<int>::iterator pos = find(v1.begin(), v1.end(), 2);
v1.insert(pos,5);
for (auto ch : v1)
{
cout << ch << " ";
}
vector<int>::iterator pos1 = find(v1.begin(), v1.end(), 2);
v1.erase(pos1);
for (auto ch : v1)
{
cout << ch << " ";
}
}
注意,迭代器不能重复使用,会报错,涉及迭代器失效
迭代器失效
在vecotr实现中详细分析
题目
杨辉三角
思路:
c语言中用二维数组来解决这个问题,c++可以用vector,每个vector就是一个数组,所以需要二维vector。题目要求返回row行,那么二维vector设置大小为row个vector,每个vecotr设置成row个元素,初始化为0,第一行和最后一行设置为1.不是1的位置等于上一行前一个元素和上一个当前元素相加
class Solution {
public:
vector<vector<int>> generate(int numRows) {
vector<vector<int>> v;
v.resize(numRows, vector<int>());
for(int i = 0; i < v.size() ; i ++)
{
v[i].resize(i + 1 , 0);
v[i][0] = v[i].back() = 1;
for(int j = 0; j < v[i].size() ; j++)
{
if (v[i][j] == 0)
{
v[i][j] = v[i-1][j-1] + v[i-1][j];
}
}
}
return v;
}
};
电话号码的字母组合
思路:
先用一个全局字符串数组记录每个按键对应的字符串。创建递归的函数,根据下标从0开始取出输入的第一个数字的字符串,从第一个字符串开始循环增加下标深度遍历,不断添加输入的数字的每个字符串。如果超过输入的数字说明可以加入返回的vector数组。整体结构是个多叉树
如,输入23,2是“abc”,3是“def”,先假如ad,再假如ae,af,bd,be,bf…
class Solution {
public:
string numstr[10] = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
void Combinations(const string& digits,size_t di,string comstr,vector<string>& strv)
{
if (di == digits.size())
{
strv.push_back(comstr);
return;
}
int num = digits[di] - '0';
string str = numstr[num];
for(auto ch:str)
{
Combinations(digits, di + 1,comstr + ch,strv);
}
}
vector<string> letterCombinations(string digits) {
vector<string> strv;
if (digits.size() == 0)
{
return strv;
}
Combinations(digits,0 ,"",strv);
return strv;
}
};
递归展开图