vector的介绍:(vector翻译是向量,但是表示的是顺序表)
vector是表示可以改变大小的数组的序列容器。
就像数组一样,vector对其元素使用连续的存储位置,这意味着也可以使用指向其元素的常规指针上的偏移量来访问它们的元素,并且与在数组中一样有效。但与数组不同的是,它们的大小可以动态变化,它们的存储由容器自动处理。
在内部,vector使用动态分配的数组来存储它们的元素。当插入新元素时,可能需要重新分配该数组以增加大小,这意味着分配一个新数组并将所有元素移至该数组。就处理时间而言,这是一项相对昂贵的任务,因此,vector不会在每次将元素添加到容器时重新分配。
相反,vector容器可能会分配一些额外的存储空间以适应可能的增长,因此容器的实际容量可能大于包含其元素所严格需要的存储空间(即其大小
)。库可以实施不同的增长策略来平衡内存使用和重新分配,但无论如何,重新分配应该只发生在对数增长的大小间隔上,以便可以为vector末尾的单个元素插入提供摊销常数时间复杂性(参见push_back)。
因此,与数组相比,vector消耗更多内存以换取管理存储和以有效方式动态增长的能力。
与其他动态序列容器(deques、list和forward_lists)相比,vector 访问其元素(就像数组一样)非常有效,并且从其末尾添加或删除元素也相对有效。对于涉及在结尾以外的位置插入或删除元素的操作,它们的性能比其他操作更差,并且迭代器和引用的一致性不如列表和forward_lists。
还是通过cplusplus.com的文档来学习,使用旧版的内容(右上角
)
vector是一个类模板,可以存储任意类型
vector和string差不多,学完了string再学vector会轻松一点
首先看构造函数:
这次的构造函数和string相比有一点不同,出现了很多没见过的类型表示方法,这些类型是由已知的类型typedef出来的,可以从Member functions上面的表格中找到对应的类型
这个是之前提到过的空间配置器(STL六大组件之一,也就是内存池,申请内存从内存池找更高效一点),这里的默认参数暂时不用管。alloc是在不想用STL中内存池,要用自己写的内存池的情况下使用的。
第一个是无参的,第四个是拷贝构造,剩下两个一会再说。
最常用的是第一个。
第二个构造函数,n表示容器大小,val表示初始化内容
第三个构造函数表示可以用迭代器区间初始化
还可以通过对迭代器加减来控制初始化区间。而且迭代器是模板类型,可以取任意类型的迭代器。比如vector<char>用string迭代器初始化。
vector的遍历方式同样也有三种:下标,迭代器,范围for
下面观察一下vector的增容机制
从结果来看大概是1.5倍扩容。Linux g++ SGI版本是2倍扩容。
单次增容越多,增容次数越少,效率越高。浪费的空间也越多。
单次增容少,增容次数越多,效率低下。
增容倍率的大小是效率与空间的平衡。
如果知道要存储多少数据,就可以通过reserve函数提前开好空间;
resize在开空间的同时还会初始化,再通过push_back插入数据不合适。
剩下的就是一些和string没什么太大区别的函数了
shrink_to_fit是缩容的函数,可以让capacity减小到和size一样大。这个要慎用,一是再存入数据要重新增容,二是这个函数是把数据存入新空间,释放原来空间来达到效果的。通常会选择用空间换时间,时间换空间的操作并不推荐,除非浪费的空间太大,否则一般不使用这个函数。
vector的insert和erase就无法通过下标进行操作了,这里要使用迭代器来操作。而且erase必须一个一个删除数据,或者给删除的区间,没有给一个位置,然后删除这个位置及位置之后的函数了。
vector和list是没有find函数的,原因在于算法库中有find函数,可以复用,包括之前的reverse(逆置)函数也在算法库中,需要包含头文件<algorithm>
还有其他算法函数,比如sort(排序)
参数时迭代器类型,迭代器也是有不同类型的。
排序算法,默认是升序。如果要排降序,涉及仿函数的知识(STL六大组件之一)。先把用法记住就行。
升序:sort(v.begin(), v.end()); 这里有默认的仿函数
降序:sort(v.begin(), v.end(), greater<int>()); 需要额外包含头文件<functional> greater就是大于的意思,也就是降序
也可以通过对象来完成降序的功能:greater<int>() g; sort(v.begin(), v.end(), g);
其他函数要么是和string几乎一样,要么以现在的知识量无法理解。
vector<char>和string也是存在区别的,比如一些函数接口的不同,如:vector是没有append函数的,也没有+=重载,所以储存字符串数据用string比较好。
下面来看看vector的OJ题
这个要是用C语言写就相当麻烦了,也能写,难度也没那么大,但不推荐。C语言刷这个的经历实在是一言难尽。
难点也就是vector<vector<int>>的遍历。
题解如下:
class Solution
{
public:
vector<vector<int>> generate(int numRows)
{
vector<vector<int>> vv(numRows);
//创建numRows个vector<int>类
for (int i = 0; i < numRows; i++)
//开好空间,完成所有1的赋值
{
vv[i].resize(i + 1);
vv[i][0] = 1;
vv[i][vv[i].size() - 1] = 1;
}
for (int i = 0; i < numRows; i++)
{
for (size_t j = 0; j < vv[i].size(); j++)
{
if (vv[i][j] == 0)
//除1以外位置的赋值
{
vv[i][j] = vv[i - 1][j - 1] + vv[i - 1][j];
//vv[i]重载,返回第i个值,返回值是vector<int>类型,继续重载[j],找到对应值。
}
}
}
return vv;
}
};