c++高级
c++ 高级部分 STL 容器
STL,英文全称 standard template library,中文可译为标准模板库或者泛型库,其包含有大量的模板类和模板函数,是 C++ 提供的一个基础模板的集合,用于完成诸如输入/输出、数学计算等功能。
STL 最初由惠普实验室开发,于 1998 年被定为国际标准,正式成为 C++ 程序库的重要组成部分。值得一提的是,如今 STL 已完全被内置到支持 C++ 的编译器中,无需额外安装,这可能也是 STL 被广泛使用的原因之一。
从根本上说,STL 是一些容器、算法和其他一些组件的集合,所有容器和算法都是总结了几十年来算法和数据结构的研究成果,汇集了许多计算机专家学者经验的基础上实现的,因此可以说,STL 基本上达到了各种存储方法和相关算法的高度优化。
Vector 数组
数组的特征:只能保存相同类型的数据、内存连续,数据具备索引,根据索引查找快,增、删慢
1 | int main() { |
stack 栈
栈的数据特点:先进后出、后进先出,类似于方法栈进栈、出栈1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19int main() {
cout << "STL stack 栈的学习" <<endl;
// 初始化
stack<int> stack1;
// 压栈
stack1.push(1);
stack1.push(2);
stack1.push(20);
stack1.push(22);
// 弹栈
stack1.pop();
cout << "栈顶元素:" << stack1.top() << endl;
// 栈没有迭代器,也没有索引 这样遍历的话,会将栈内元素都弹出。
while (!stack1.empty()) {
cout << "遍历栈元素:" << stack1.top() << endl;
stack1.pop();
}
return 0;
}
压栈、弹栈函数都是没有返回值的,
top函数获取栈顶元素
queue 队列
队列的数据特点: FIFO 先进先出,后进后出。与栈不同
队列内部可以使用数组实现、也可以使用链表实现
1 | int main() { |
优先级队列
优先级队列是队列的一个子集,内部数据结构通过数组实现,而且是数据有序排练,默认是降序。
不论数据push的顺序,直接给你降序处理,可以设置成升序排列
1 | int main() { |
list 链表
链表的数据特点,内存非连续,每个节点有下一个节点的指针,增删快,但查询慢,增加、删除都只能在表头操作
1 | int main(){ |
set 红黑树
内部结构 红黑树 会对你存入的数据进行排序,但是绝对不允许元素相同
默认会升序排列,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30int main() {
cout << "STL 五 set 学习" << endl;
set<int>setV;
// 插入值
// 默认会升序排列
setV.insert(80);
setV.insert(70);
setV.insert(50);
setV.insert(90);
// 当插入已经存在的值时,会失败,因为不允许重复
pair<set<int, less<int>>::iterator, bool> result = setV.insert(60);
// 注意set的insert函数是有返回值的,first是迭代器 second是插入的结果
if(result.second) {
// 插入成功
cout << "插入成功" << endl;
// 注意此处取得的迭代器不是从begin开始,而是从插入的值60处开始的。
for(; result.first != setV.end(); result.first ++) {
cout << "插入结果迭代器遍历的值:" << * result.first << endl;
}
} else {
cout << "插入失败" << endl;
}
// 迭代器遍历
for(set<int>::iterator it = setV.begin(); it != setV.end(); it ++) {
cout << "迭代器遍历的值:" << * it << endl;
}
return 0;
}
谓词
转自:https://www.cnblogs.com/xym4869/p/12250174.html
1.函数(function)谓词
通过传递函数名, 匹配二元谓词(binary predicates), 根据函数提供的策略, 输出值;
1 | /*Function Predicate*/ |
2.函数指针(function pointer)谓词
建立一个函数指针, 传入算法, 使用指针代替函数名, 用法类似函数谓词.
1 | bool (*pf) (const std::string &s1, const std::string &s2); |
3.Lambda表达式(lambda expression)谓词
Lambda表达式格式: [capture list] (parameter list) -> return type { function body }
需要匹配谓词数, 一元(unary) 或 二元(binary), 也可以通过[capture list]传递函数的变量;
1 | std::stable_sort(sv.begin(), sv.end(), |
4.函数对象(Function Object)谓词
类中重载函数的调用”()”, 使类可以被调用, 并且传入算法谓词中, 进行使用.
1 | /*Function Object*/ |
5、结构体谓词
1 | // 真正的谓词 |
map
map: key value键值对容器,默认会对key进行排序,所以不能存在重复的key,会添加失败 value可以重复1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32int main(){
cout << "STL 六 map学习" << endl;
map<int, string>mapVar;
// 插入值 需要借助 std::pair
mapVar.insert(pair<int, string>(1, "justin"));
mapVar.insert(pair<int, string>(5, "justinA"));
mapVar.insert(pair<int, string>(3, "justin"));
// 使用迭代器遍历
for(map<int, string>::iterator it = mapVar.begin(); it != mapVar.end(); it++) {
cout << "key:" << it->first << " value:" << it->second <<endl;
}
// 获取插入值的结果
pair<map<int,string>::iterator, bool> result = mapVar.insert(pair<int, string>(4, "novia"));
if(result.second) {
cout << "插入值成功" << endl;
// 因为有排序,只会遍历从4以及4以后的元素
for(; result.first != mapVar.end(); result.first ++) {
cout << "key:" << result.first->first << " value:" << result.first->second <<endl;
}
} else {
cout << "插入值失败" << endl;
}
// 查询 是根据key查询的
map<int, string>::iterator findResult = mapVar.find(3);
if(findResult != mapVar.end()) {
cout << "已找到" << findResult -> first << ", " << findResult->second.c_str() << endl;
} else {
cout << "查找key失败" << endl;
}
return 0;
}
multimap
multimap 属于 map下的子集
// 1.key可以重复, 2.key重复的数据可以分组, 3.key会排序, 4.value不会排序1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41int main(){
cout << "STL 七 multimap学习" << endl;
multimap<int, string>multimapVar;
multimapVar.insert(make_pair(10, "justin"));
multimapVar.insert(make_pair(10, "novia"));
multimapVar.insert(make_pair(10, "justin"));
multimapVar.insert(make_pair(20, "justin"));
multimapVar.insert(make_pair(20, "novia"));
multimapVar.insert(make_pair(20, "coco"));
multimapVar.insert(make_pair(30, "justin1"));
multimapVar.insert(make_pair(30, "justin2"));
multimapVar.insert(make_pair(30, "justin3"));
for(multimap<int, string>::iterator it = multimapVar.begin(); it != multimapVar.end(); it++) {
cout << it->first << ", " << it -> second << endl;
}
// TODO 核心功能是分组
int result;
cout << "请输入你要查询的key,为int类型:" << endl;
cin >> result;
multimap<int, string>::iterator iteratorVar = multimapVar.find(result);
while (iteratorVar != multimapVar.end()) {
cout << iteratorVar->first << "," << iteratorVar->second << endl;
// 需要自己做逻辑控制,不然有问题
iteratorVar++;
if (iteratorVar->first != result) {
break;; // 循环结束
}
// 严谨性
if (iteratorVar == multimapVar.end()) {
break;; // 循环结束
}
}
return 0;
}
防函数
1 | class TestForEach{ |
在源码中有很多防函数的使用,其实我们自己可以手动实现一个防函数,并替换源码中的
1 | // 自定义加法 |
关于模版函数
1 | // 定义模版 Params1 第一个参数类型 Params2 第二个参数类型 ReturnType 返回值类型 |