一. vector 容器
vector 容器是标准库中的一种顺序容器,它是可变大小数组,支持快速随机访问。在尾部之外的位置插入或删除元素可能会很慢
创建 vector 容器
std::vector<int> vec_1 = {1, 2, 3, 4};
std::vector<int> vec_1 = {1, 2, 3, 4};
std::vector<int> vec_2(vec_1);
std::vector<int> vec_1(5, 1);
访问 vector 容器
for(const auto &elem : vec_1)
printf("%d ", elem);
printf("\n");
for(int i = 0; i < vec_1.size(); ++i)
printf("%d ", vec_1[i]);
printf("\n");
for(auto iter = vec_1.begin(); iter != vec_1.end(); ++iter)
printf("%d ", *iter);
printf("\n");
尾部插入元素
std::vector<int> vec_1;
vec_1.emplace_back(1);
vec_1.emplace_back(2);
vec_1.emplace_back(3);
尾部删除元素
vec_1.pop_back();
vec_1.pop_back();
vec_1.pop_back();
删除迭代器指定范围的元素
std::vector<int> vec_1 = {1, 2, 2, 4, 5};
vec_1.erase(vec_1.begin()+1, vec_1.end()-2);
如何删除 vector 容器中满足一定条件的元素?
二. lambda 表达式
2.1 简介
lambda 表达式表示一个可调用的代码单元,可以将其理解为匿名函数,和函数不同的是,lambda 可能定义在函数内部。
[capture list](parameter list) -> return type {function body}
形参列表与返回类型可以省略,但是必须永远包含捕获列表与函数
捕获列表用来捕获当前函数作用域的 0 个或多个变量,变量之间用逗号隔开。有两种捕获方式:按值捕获和按引用捕获
2.2 练习
比大小
#include <cstdio>
int main(void){
auto lambda_1 = [](int num_1, int num_2){ return num_1 >= num_2? num_1 : num_2; };
printf("Max: %d\n", lambda_1(4, 5));
return 0;
}
求绝对值
#include <cstdio>
int main(void){
auto lambda_1 = [](int num_1){ return num_1 >= 0? num_1 : -num_1; };
printf("Abs: %d\n", lambda_1(-7));
return 0;
}
求平方
#include <cstdio>
int main(void){
auto lambda_1 = [](int num_1){ return num_1 * num_1; };
printf("Sqrt: %d\n", lambda_1(-7));
return 0;
}
2.3 按值捕获
捕获列表只能捕获非静态的局部变量,对于静态局部变量和全局变量,直接拿来使用就可以了
值捕获是将捕获变量拷贝到 lambda 表达式内,因此要求捕获变量可以拷贝;并且默认无法改变捕获变量的值;但可通过 mutable 说明符移除 lambda 表达式的常量性,此时 parameter list 不可省略;
#include <cstdio>
int num_1 = 999;
int main(void){
// 报错!!!,无法捕获全局变量
auto lambda_1 = [num_1]{ return num_1 * num_1; };
printf("Test: %d\n", lambda_1());
return 0;
}
#include <cstdio>
int main(void){
int num_1 = 999;
auto lambda_1 = [num_1]{
// 报错!!!,值捕获的变量默认为常量
++num_1;
printf("Test: %d\n", num_1);
return;
};
lambda_1();
return 0;
}
#include <cstdio>
int main(void){
int num_1 = 999;
auto lambda_1 = [num_1]() mutable {
++num_1;
printf("num_1: %d\n", num_1);
return;
};
lambda_1();
lambda_1();
lambda_1();
printf("num_1: %d\n", num_1);
return 0;
}
可以发现
- 按值捕获,无论在 lambda 表达式内如何改变捕获变量的值,不会影响外部作用域
- 但是,它却能影响下次调用 lambda 表达式时捕获变量的值
- 按值捕获,捕获变量的值在 lambda 表达式定义的时候就固定下来了,之后无论如何修改外部作用域的值,lambda 捕获的值都不会变化
2.4 按引用捕获
按引用捕获只需在捕获变量前加 &
#include <cstdio>
int main(void){
int num_1 = 999;
int num_2 = 666;
auto lambda_1 = [&num_1, &num_2](){
++num_1;
++num_2;
return;
};
printf("num_1: %d, num_2: %d\n", num_1, num_2);
lambda_1();
printf("num_1: %d, num_2: %d\n", num_1, num_2);
return 0;
}
按引用捕获,可以改变捕获变量的值,并且会影响外部作用域
使用 lambda 表达式时,优先使用按值捕获,必要时使用按引用捕获
三. STL 常用算法
3.1 映射
transform(begin, end, result, op);
1. begin:容器的开始迭代器
2. end:容器的结束迭代器
3. result:存放结果的开始迭代器
4. op: 可调用对象
#include <cstdio>
#include <vector>
#include <algorithm>
int main(void){
std::vector<int> vec_1 = {1, 2, 3, 4};
show(vec_1);
// 平方
std::transform(vec_1.begin(), vec_1.end(), vec_1.begin(), [](int elem){ return elem * elem; });
show(vec_1);
return 0;
}
int main(void){
std::vector<int> vec_1 = {1, 2, 3, 4};
show(vec_1);
// 取反
std::transform(vec_1.begin(), vec_1.end(), vec_1.begin(), [](int elem){ return -elem; });
show(vec_1);
return 0;
}
3.2 过滤
remove_if(begin, end, op)
1. begin:容器的开始迭代器
2. end:容器的结束迭代器
3. op: 谓词
remove_if 并不会实际移除容器中的元素,只是将应该移除的元素都移动到了容器尾部,并返回一个分界的迭代器
int main(void){
std::vector<int> vec_1 = {1, 2, 3, 4};
show(vec_1);
// 过滤偶数
vec_1.erase(std::remove_if(vec_1.begin(), vec_1.end(), [](int elem){ return elem % 2 == 0; }), vec_1.end());
show(vec_1);
return 0;
}
int main(void){
std::vector<int> vec_1 = {-1, 2, -3, 4};
show(vec_1);
// 过滤负数
vec_1.erase(std::remove_if(vec_1.begin(), vec_1.end(), [](int elem){ return elem < 0; }), vec_1.end());
show(vec_1);
return 0;
}
3.3 折叠
accumulate(begin, end, init, op)
1. begin:容器的开始迭代器
2. end:容器的结束迭代器
3. init:初始值
4. op: 可调用对象
int main(void){
std::vector<int> vec_1 = {1, 2, 3, 4};
show(vec_1);
// 累加
int res = std::accumulate(vec_1.begin(), vec_1.end(), 0, [](int elem_1, int elem_2){ return elem_1 + elem_2; });
printf("Res: %d\n", res);
return 0;
}
int main(void){
std::vector<int> vec_1 = {1, 2, 3, 4};
show(vec_1);
// 累乘
int res = std::accumulate(vec_1.begin(), vec_1.end(), 1, [](int elem_1, int elem_2){ return elem_1 * elem_2; });
printf("Res: %d\n", res);
return 0;
}
标准库中,还有一些顺序容器,如 deque 双端队列、list 双向链表、forward_list 单向链表和 array 固定大小数组。
作业
给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。
根据维基百科上 h 指数的定义:h 代表“高引用次数”,一名科研人员的 h指数是指他(她)的 (n 篇论文中)总共有 h 篇论文分别被引用了至少 h 次。且其余的 n - h 篇论文每篇被引用次数 不超过 h 次。
如果 h 有多种可能的值,h 指数 是其中最大的那个。
示例 1:输入:citations = [3,0,6,1,5]
输出:3
解释:给定数组表示研究者总共有 5 篇论文,每篇论文相应的被引用了 3, 0, 6, 1, 5 次。由于研究者有 3 篇论文每篇 至少 被引用了 3 次,其余两篇论文每篇被引用 不多于 3 次,所以她的 h 指数是 3。
示例 2:输入:citations = [1,3,1]
输出:1