[LeetCode刷题笔记] C++ vector常用操作

在[1]对常用的STL容器进行了概览,笔者在刷题过程中经常需要查询一些STL容器的函数,实为不便,因此在此对STL容器中常用的操作进行笔记。


std::vector是一种线性数组,每个元素的数据类型都相同,不过和一般的静态的数组不同的是,其允许通过插入元素,删除元素实现所谓的动态数组,是常用的数据结构,类似于python中的列表list

其涉及到的常用操作有几大类:

  1. 初始化操作,涉及到初始化数组时候的一些操作。
  2. 检索index,对指定位置的元素进行读取或者修改。
  3. 插入元素,在某个指定位置或者某个位置区间插入特定的元素。
  4. 删除元素,在某个特定的位置或者区间删除元素。
  5. 遍历元素,属于检索元素的一种,不过其操作具有一般性,因此特地拿出来讨论。
  6. 其他操作,包括对元素进行排序sort,检查是否有特定元素等。

接下来进行概览和举例说明。
PS: vector.begin()指向vector的第一个元素的位置,vector.end()指向vector的最后一个元素的后一个位置。


1. 初始化操作

vector的构造函数为:

template < class T, class Alloc = allocator<T> > class vector; // generic template

可以用vector<data_type> 选择元素的数据类型。一般有如下几种常用的初始化方式:

vector<int> first; // 空的vector,只是一个列表的头,里面没有元素
vector<int> second (4, 100); // 初始化一个具有4个元素的vector,每个元素的值都是100
vector<int> third (second.begin(), second.end()); // 通过其他vector的迭代器的方式,进行拷贝复制初始化
vector<int> fourth (third); // 直接对其他vector的拷贝复制

int myints[] = {16, 2, 77};
vector<int> fifth (myints, myints+sizeof(myints) / sizeof(int)); // 将数组转化成vector,需要提供的是数组的首地址和地址偏移。

vector<int> sixth = {1,5,4,6}; // 指定内容进行构造,内容为1,5,4,6的vector

在作为函数返回或者传参数时,可以进行匿名的构造,也就是不需要给予变量名字,如:

return vector<int>(); // 此时返回的就是空的vector
return vector<int>{1,4,5}; // 此时返回的是{1,4,5}
foo(vector<int>{1,4,5})

也可以实现多重vector

vector< vector<int> > vars;
// 二维vector的初始化
int size = 10;
vector<vector<int>> vars(size, vector<int>(size, 0)); // (size,size)的矩阵,元素全部是0

2. 索引元素

索引其元素和索引一般的数组元素相似

vector<int> first = {1,3,4,5,6};
first[1]; // 直接索引
first[1] = 0; //直接可以修改
first.at(1) = 0; // 也可以通过函数索引
*(first.begin()+3); // 也可以通过对迭代器取值得到,而且可以提供偏移比如+3.
first.back(); // 获取vector的最后一个元素

3. 遍历元素

遍历元素可以通过以下方式进行:

  1. 采用迭代器
vector<int> vars = {1,3,5,6,7,8};
for (vector<int>::iterator it = vars.begin(); it != vars.end(); ++it){
	*it = 10; // 遍历每一个元素
}

通过对迭代器进行加减可以实现遍历某一区间的元素:

vector<int> vars = {1,3,5,6,7,8};
for (vector<int>::iterator it = vars.begin()+1; it != vars.end()-1; ++it){
	*it = 10; // 遍历每一个元素
}

当然如果你用auto关键字,你也可以这样:

vector<int> vars = {1,3,5,6,7,8};
for (auto it = vars.begin(); it != vars.end(); ++it){
	*it = 10; // 遍历每一个元素
}
vector<int> vars = {1,3,5,6,7,8};
for (auto &v:vars)
	cout << v << endl;

这种方法对于遍历所有元素很方便

  1. 用索引的方式遍历,这种方式是最直接的
vector<int> vars = {1,3,5,6,7,8};
int vsize = vars.size();
for (int i = 0; i < vsize: ++i){
	vars[i];
}

4. 插入元素操作

对于线性的vector来说,如果是在最后一个位置添加一个元素,类似于python中的list.append(),那么可以:

vector<int> vars ;
vars.push_back(10);

如果是需要在中间的某个位置插入元素,用insert():

vector<int> vars = {1,2,3,4,5};
vars.insert(vars.begin(), 100); // 插入单个元素,在vars的第0元素位置插入100,位置用迭代器表示
vars.insert(vars.begin(), 2, 100); // 插入多个相同的元素,此处插入2个100

vector<int> cop = {6,7,8};
vars.insert(vars.end(), cop.begin(), cop.end()); // 也可以进行vector之间的拼接

5. 删除元素

vector<int> vars = {1,2,3,4,5,6};
vars.pop_back(); // 弹出最后一个元素,注意只是弹出,不返回其值,用vector.back()返回其值
vars.clear(); // 清空vector
auto iter = vars.erase(vars.begin()+1); 
// 删除单个元素,指定迭代器,删除后vector的大小减1,但是容量不变。
// 其返回一个迭代器,指向被删除元素后的第一个元素。
auto iter = vars.erase(vars.begin(), vars.begin()+2); // 删除一个范围内的值,指定开头,结尾的迭代器即可。

其中在algorithm头文件中提供了remove操作,其本质是对vector中的值进行匹配,如果匹配到了,则移到vector的末端。
例如

std::vector<std::string> words { "one", "none","some", "all”, "none", "most","many"};
auto iter = std::remove(std::begin(words), std::end(words), "none");

此处第二句将会匹配words中的字符串none,并且检查其后一个元素,如果是不符合none的,则把它前移,覆盖掉前一个的none,就结果而言,vector中的最后的若干个元素都变成了none,因此这里的remove并不是实质上的移除,而是移到了末尾的位置,并且将其设为了空字符串。如果此时用vector.size()我们会发现其大小并没有改变。
在这里插入图片描述
为了释放最后的无用的空间,我们结合erase,有:

words.erase(iter, words.end()); // 此处的iter是由remove返回的迭代器

6. 其他操作

其他常见的操作有sort排序,max_element求最大值, min_element求最小值, find查找值,swap交换值,distance查找值的位置等函数,这些函数在头文件<algorithm>中。

  1. sort排序
vector<int> vars = {2,4,1,6,7,3,9};
sort(vars.begin(), vars.end()); // 默认是升序排列,输出如 1,2,3,4,6,7,9
// 也可以指定特定的排序函数,取代默认的升序排序,甚至可以对非数值类型的数据结构进行排序。
bool sortFunc(const int &num1, const int &num2) {
	return num1 > num2 ; // 降序排序
	// return num1 < num2; 升序排序
	// 返回为true的将会放置于之前,false的元素为之后
}
sort(vars.begin(), vars.end(), sortFunc);
  1. max_element, min_element
vector<int> vars = {2,4,1,6,7,3,9};
auto iter = max_element(vars.begin(), vars.end()); // 返回的是迭代器,指向的是最大值的位置,需要取值的话加*取值。
int max_value = *iter;
auto iter = min_element(vars.begin(), vars.end()); // 返回的是迭代器,指向的是最小值的位置,需要取值的话加*取值。
int min_value = *iter;

通过指定特定比较函数,可以实现不同数据结构的比较,如:

struct node {
    int x, y;
};
bool cmp1(node a, node b) {
    return a.x > b.x;
}
vector<node> v1(3);
node max_node = *max_element(v1.begin(), v1.end(), cmp1);
  1. find查找值的位置
    此函数返回第一个匹配指定值的数据的位置。
vector<int> vars = {1,2,3,4,5,6};
int myints[] = {1,2,3,4,5,6};

int *p = find(myints, myints+6, 5); // 查找数值5的位置,如果找到了返回其位置的指针,否则将指向最后一个元素的下一个元素的位置,如
if (p != myints+6)
	cout << "found in myints at location :" << p-myints << endl;
else
	cout << "element not found in the arrays" << endl;
	
// 同样的,对于vector也是适用的
vector<int>::iterator iter = find(vars.begin(), vars.end(), 5);
if (iter != iter.end())
	cout << "found in myints at location :" << iter-vars.begin() << endl;
else
	cout << "element not found in the arrays" << endl;
  1. distance求距离
    求指定的迭代器之间的元素距离,类似于指针地址详见,该函数在头文件<iterator>,如:
vector<int> vars = {1,2,3,4,5,6};
vector<int>::iterator iter = find(vars.begin(), vars.end(), 5);
cout << distance(vars.begin(), iter) << endl; // 类似于 iter-vars.begin()

Reference

[1]. https://blog.csdn.net/LoseInVain/article/details/104189784

posted @ 2020-02-23 01:05  FesianXu  阅读(228)  评论(0编辑  收藏  举报