vector的使用和模拟实现
一.vector的介绍和使用
在C++中,vector是标准库提供的一种动态数组容器,它可以按顺序的存储相同元素,同时具备多种性能,比如,可以根据存储数据的大小来调整自身的容量,另外所有元素在内存中是连续存放的,这使得通过下标进行随机访问的效率极高。自动处理内存的分配与释放,降低了内存泄漏的风险等等。
1.1 vector的一些基础使用
在学习vector的时候一定要学会看vector的文档,他就像说明书一样指导我们怎样去使用一个函数,传哪些参数等等,下面我会挑一些重要的接口和函数为大家介绍。
1.1.1 vector的定义
其中使用vector要明白其构造函数的用法,每种构造函数适用于不同参数的传递,在我们打开vector的文档就能知道,其构造函数也是多种多样的。
int main()
{vector<int> v1; //创建一个空vector,默认构造函数v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);v1.push_back(6);for (auto e : v1){cout << e << " ";}cout << endl;vector<int> v2(5, 10);//创建包含5个元素的vector,每个元素值为10for (auto e : v2){cout << e << " ";}cout << endl;//用迭代器的方法去初始化vectorint arr[] = { 1,2,3,4 };vector<int> v3(arr,arr+4);for (auto e : v3){cout << e << " ";}cout << endl;//拷贝构造函数vector<int> v4 = { 6,7,8,9 };vector<int> v5(v4); //创建一个新的对象去拷贝构造原本已经存在的对象元素return 0;
}
上面的代码就一一展示了默认构造函数,传参构造函数,拷贝构造函数等等,我们可以根据不同的情况去调用不同的构造函数。
1.1.2 vector迭代器的使用
我们通过查询文档可以看到多种迭代器的使用,这里只拿几个典型的来使用,比如说begin和end就是获取第一个数据位置的迭代器和获取最后一个数据的下一个位置的迭代器。
//迭代器的使用
int main()
{vector<int> v1 = { 1,2,3,4,5 };//使用迭代器进行输出for (vector<int>::iterator it1 = v1.begin(); it1 != v1.end(); ++it1){cout << *it1 << " ";}cout << endl;vector<int> v2 = { 1,2,3,4,5 };for (vector<int>::reverse_iterator rit2 = v2.rbegin(); rit2 != v2.rend(); ++rit2){cout << *rit2 << " ";}cout << endl;return 0;
}
1.1.3 vector空间增长问题
首先capacity是获取容量的大小,size是获得数据元素的个数,resize是改变vector的size,reserve是改变vector的capacity,max_size顾名思义就是获取vector在理想状态下能够容纳的最多元素。另外capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。resize在开空间的同时还会进行初始化,会影响szie。
//vector的容量问题
int main()
{vector<int> v1;for (int i = 0; i < 10; i++){v1.push_back(i);}for (auto e : v1){cout << e <<" ";}cout << endl;cout << v1.capacity() << endl;cout << v1.size() << endl;cout << v1.max_size() << endl;return 0;
}
1.1.4 vector容量接口使用
//vector的接口使用
int main()
{vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);for (auto e : v1){cout << e << " ";}cout << endl;v1.pop_back();v1.pop_back();v1.pop_back();for (auto e : v1){cout << e << " ";}cout << endl;//insert插入vector<int>::iterator it = v1.insert(v1.begin() + 1, 10);for (auto e : v1){cout << e << " ";}cout << endl;//erase删除vector<int> v2 = { 4,5,6,7,8,9 };v2.erase(v2.begin() + 2);for (auto e : v2){cout << e << " ";}cout << endl;//swap交换vector<int> v3 = { 2,3 };vector<int> v4 = { 4,5 };swap(v3, v4);for (auto e : v3){cout << e << " ";}cout << endl; for (auto e : v4){cout << e << " ";}cout << endl;//operator[]的使用vector<int> v5 = { 8,9,10 };cout << "索引是2的元素" << v5[2] << endl;return 0;
}
1.2 vector在OJ中的使用
(1) 只出现一次的数字
class Solution {
public:int singleNumber(vector<int>& nums) {int value =0;for(auto e: nums){value^=e;}return value;}
};
这是一个典型的题目,是我们口中常说的“单身汉问题”,这个题目使用到了按位异或的知识点,我们需要知道当一个数与自身按位异或的时候结果等于0,与0按位异或的时候等于自身,而这个题目又刚好是某个元素出现一次,其他元素出现两次,所以相当于是其他的元素出现两次之后都与自身按位异或,所以最终的结果都是只出现一次的元素与0按位异或,所以最终输出的结果就是只出现了一次的元素。
(2) 杨辉三角的实现
class Solution {
public:vector<vector<int>> generate(int numRows) {vector<vector<int>> vv(numRows);for (int i = 0; i < numRows; ++i){vv[i].resize(i + 1, 1);}for (int i = 2; i < numRows; ++i){for (int j = 1; j < i; ++j){vv[i][j] = vv[i - 1][j] + vv[i - 1][j - 1];}}return vv;}
};
这道题目主要是运用了vector的便捷性生成了二维数组,不再使用C语言中的指针等复杂的语法,能够以更加简单方便理解的方式来完成题目。