《Cpp STL - vector常用语法》
STL,英文全称 standard template library,中文可译为标准模板库或者泛型库,其包含有大量的模板类和模板函数,是 C++ 提供的一个基础模板的集合,用于完成诸如输入/输出、数学计算等功能。很多人对C++望而却步是因为很多内存问题及线程安全问题无法掌控,导致不友好,而STL已经能够很好的规避这些问题了,比如使用vector的内存管理就不需要你担心了,但是vector的动态内存有时候会很慢,因为vector每次会根据你的需求的2倍来申请内存的,所以当你的数组特别大的时候可能会申请很多次内存,导致效率低,当然,vector也有reserve或者resize这样的方法,有malloc是类似的功能,如果使用malloc记得free也没什么问题。
Key Words:vector各种操作的复杂度、vector常用属性和方法、vector排序、lambda表达式
Beijing, 2020
作者:RaySue
Code:
文章目录
vector 初始化
一维
// 初始化 n 个 0
vector<int> a(n, 0);
二维
// 初始化 m 行 n 列 个 0
vector<int> a(m, vector<int>(n, 0));
操作复杂度(最差)
访问 | push_back() | push_front() | insert() | pop_back() | pop_front() | erase() | find() | |
---|---|---|---|---|---|---|---|---|
vector | O(1) | O(1) | \ | O(n) | O(1) | \ | O(n) |
容量 Capacity
vector 的容量是根据当前元素进行动态扩容的,在堆中分配内存,元素连续存放,有保留内存,如果减少大小后,内存也不会释放;如果新值大于当前大小时才会重新分配内存,在新增数据的时候,就要分配一块更大的内存,将原来的数据复制过来,释放之前的内存,再插入新增的元素,不同的编译器实现的扩容方式不一样,VS2015中以1.5倍扩容,GCC以2倍扩容。
所以如果 vector 需要存储的 size 比较大的情况,应该提前使用 reserve 指定其 size,否则非常耗时。
初始时刻 vector 的 capacity 为0,塞入第一个元素后 capacity 增加为1。
- capacity //总共能够容纳元素的个数
- size //当前已经容纳元素的个数
- max_size // 容器所能容纳的最大数目的元素个数,这是系统或者库所实施的限制
- reserve // Request a change in capacity
- resize // Change size
- empty //是否为空
迭代
- 顺序迭代
- 下标迭代
- 迭代器迭代
元素访问 Element access
- operator []
- at
- front // Access first element
- back // Access last element
修改 Modifiers
- assign // Assign vector content
- push_back
- pop_back
- insert // 可以在任意位置插入一段vector,也可以push_front,就是线性复杂度
- swap // Swap content
- clear // 清空容器内的所有内容
vector 的常用方法
vector 的逆序
reverse(vec.begin(), vec.end());
vector 的 find 方法
- find 方法返回的结果是迭代器,指向值为 ‘寻找值’ 的第一个元素的位置
- 转换迭代器为下标的方法是减去容器的begin()
vector<double>::iterator ite1 = find(vec_dis.begin(), vec_dis.end(), 6);
vector<double>::iterator ite2 = find(vec_dis.begin(), vec_dis.end(), 7);
vector<double>::iterator ite3 = find(vec_dis.begin(), vec_dis.end(), 8);
auto index1 = ite1 - vec_dis.begin();
// or
auto index1 = std::distance(std::begin(vec_dis), ite1);
auto index2 = std::distance(std::begin(vec_dis), ite2);
auto index3 = std::distance(std::begin(vec_dis), ite3);
vector的删除操作
- erase + remove // 删除所有值为 x 的元素
// 单独执行remove不会删除x元素,会返回一个迭代器
remove(vec.begin(), vec.end(), x)
// 删除元素的完整写法
vec.erase(remove(vec.begin(),vec.end(), x),vec.end());
vector的insert方法
A.insert(A.end(), B.begin(), B.end());
通过insert的push_front方法
- 此方法复杂度较高为O(N),N为数组的长度,酌情使用
// 向数组 A 的头部插入数值 6
A.insert(A.begin(), 6);
通过insert 实现 extend方法
// eq:A.extend(B)
// 1
// reserve() is optional - just to improve performance
A.reserve(A.size() + distance(B.begin(), B.end()));
A.insert(A.end(), B.begin(), B.end());
// 2
copy(B.begin(), B.end(), back_inserter(A));
// 3
A.reserve(A.size() + B.size());
A.insert(A.end(), B.begin(), B.end());
A.insert(std::end(A), std::begin(B), std::end(B));
count方法
string temp = "aaabcdaaa!!!";
int num = count(temp.begin(),temp.end(),'a');
cout <<"在字符串" << temp << "中," <<"字母a出现的次数是" << num << endl;
求最值
- 数组
int num[]={2,3,1,6,4,5};
cout<<"最小值是 "<<*min_element(num, num+6)<<endl;
cout<<"最大值是 "<<*max_element(num, num+6)<<endl;
- vector
vector<int> nums = {2,3,1,6,4,5};
cout<<"最小值是 "<<*min_element(nums.begin(), nums.end())<<endl;
cout<<"最大值是 "<<*max_element(nums.begin(), nums.end())<<endl;
vector 的排序
lambda 表达式
C++11 提供了对匿名函数的支持,称为 Lambda 函数(也叫 Lambda 表达式)。Lambda 表达式把函数看作对象。Lambda 表达式可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值。Lambda 表达式本质上与函数声明非常类似。
auto lambda = [](int a, int b){return a + b;};
// 值传递
auto lambda = [=]{return a + b;};
// 引用传递
auto lambda = [&]{a++; b++; return a + b;};
vector 的lambda排序
-
[capture](parameters) mutable ->return-type{statement}
-
capture 捕捉列表,可以捕捉变量,如果是=可以捕捉所有父作用域的变量包括this
-
parameters 表示入参
-
mutable 可以无返回
-
return-type 表示返回类型
// 降序排序
auto lambda = [](int a, int b)->bool{return a > b;};
sort(nums.begin(), nums.end(), lambda);
对vector<vector>进行降序排序
sort(a.begin(), a.end(), [](vector<int> a1, vector<int> a2)->bool{return a1[0] > a2[0];});
- []表示捕捉列表,这里为空,表示不需要捕捉任何变量,常见的有=和&,或指定一个数组
- parameters 表示入参 a1, a2
- {} 里面表示执行的函数
vector 的 argsort 排序
auto lambda = [&nums](int a, int b)->bool {return nums[a] < nums[b];};
sort(idx.begin(), idx.end(), lambda);
- 这里传入的是nums变量的引用,如果父作用域有nums,这里也可以用 =
- 其中idx是 {0,1,2,3,…} 有序的下标
- nums 是待排序的数组