STL 在广义上主要分为三类:
1. algorithm(算法):完成特定的功能
2. container(容器):用于存储数据
3. iterator(迭代器): 类似于指针,用于访问容器中的内容
STL - Algorithm(算法)
STL 中大部分的算法都在 <algorithm> 库中,用的时候只需要在头文件中包含进来即可
#include <algorithm>
* 接下来介绍几个在程序中常使用的算法:
STL - Algorithm(算法) - min, max(取最值)
* min(x, y):取两者中的较小值
* max(x, y):取两者中的最大值
- 它们调用起来十分简单,只要满足 x,y 是相同类型,并
且可以比较大小即可。
int a = 5, b = 4, c = min(a, b); // c = 4 double x = 1.5, y = 3.5, z = max(x, y); // z = 3.5
STL - Algorithm(算法) - swap(交换)
* swap(x, y):交换两者的值
- 调用时只要满足 x,y 是相同类型即可。
int a = 5, b = 4; swap(a, b); // a = 4, b = 5 double x = -1.0, y = 2.5; swap(x, y); // x = 2.5, y = -1.0 // !swap(a, x) 无法调用:类型不相同
STL - Algorithm(算法) - sort(排序)
* sort(first, last):对于在 [first, last) 中的元素进行排序
* sort(first, last, comp):对于在 [first, last) 中的元素进行排序,其中 comp 为比较器
int a[10] = {5, 2, 1, 3, 4}; sort(a, a+5);// a = [1, 2, 3, 4, 5, ...] 普通排序 int cmp(int x, int y){return x > y;} // 比较器 sort(a, a+5, cmp);// a = [5, 4, 3, 2, 1, ...] 从大到小排序
int a[10] = {5, 2, 1, 3, 4}; sort(a, a+5);// a = [1, 2, 3, 4, 5, ...] 普通排序
* 几点需要注意的地方:排序的区间为[first, last),左闭右开;
如果需要排序A[1..5]中的数,则需要调用sort(A+1, A+6);
* 可以自己定义比较器,作为排序的准则:例如,我们需要按照个
位数来比较大小,则可以定义比较器为
int cmp(int x, int y){return x % 10 < y % 10;}
* 对于自己定义的结构体,可以定义自己的比较器来实现排序功能。
// 以 a 为第一关键字,b 为第二关键字进行排序 int cmp(Mystruct x, Mystruct y) {return x.a == y.a ? x.b < y.b : x.a < y.a;}
STL - Algorithm(算法) - lower_bound (查找)
* lower_bound(first, last, element):给定 [first, last)
中的已经从小到大好排序的元素,找出最前的一个不比 element
要小的元素的位置
int a[10] = {5, 2, 1, 3, 4, 3, 2, 4}; sort(a, a+8); // a = [1, 2, 2, 3, 3, 4, 4, 5] 已从小到大排好序 int p2 = lower_bound(a, a+8, 2) - a; // p2 = 1 // a中最前的不比 2 小的元素是: a[1] = 2 int p4 = lower_bound(a, a+8, 4) - a; // p4 = 5 // a中最前的不比 4 小的元素是: a[5] = 4 int p0 = lower_bound(a, a+8, 0) - a; // p0 = 0 // a中最前的不比 0 小的元素是: a[0] = 1 int p6 = lower_bound(a, a+8, 6) - a; // p6 = 8 // a中没有不比 6 小的元素,所以返回最后的一个位置 a[8] // 注意:a[8] 中并没有值,是数组的最末端
STL - 容器 (Container)
* STL 中的容器被分配在不同的库中,用的时候只需要在头文件中
包含对应的库即可
#include <vector> // 向量:用于存储连续的元素,类似数组 #include <set> // 集合 #include <queue> // 队列 #include <stack> // 栈 #include <map> // 映射:相当于一个坐标无限大的数组 #include <priority_queue> // 优先队列:类似于堆 #include <list> // 列表:类似于链表
* 接下来介绍几个在程序中常使用的容器。
STL - 容器 (Container) - 向量 (vector)
* 向量 (vector):用于存储连续的元素,类似数组;并且可以动态改变数组的大小(不必提前声明数组大小)
//vector声明 vector<int>a; vector<int>b(5, 0); int n; //vector访问 void vis() { for(int i=0; i<5; i++) b[i] = i; for(int i=0; i<5; i++) cout<<b[i]<<" "; return ; } //vector添加元素 void add() { cin>>n; for(int i=0; i<n; i++) a.push_back(i * i);//尾部插入数字 for(int i=0; i<n; i++) cout<<a[i]<<" "; return ; } //插入元素 a.insert(a.begin()+i,xx); //在第i+1个元素前面插入xx //删除元素 a.erase(a.begin()+i); //第i+1个元素被删除 //vector设定长度 vector<int>c; c.resize(5);//设置c的大小为5,下标 //vector长度(数组大小) int len = c.size(); //len = 5 在此时c[4] 是可以访问的 //vector清空 c.clear();//清空c数组 vector一旦清空,长度变为0,所以不可以访问c[4]
* 向量 (vector)还有更多的内置函数,这里就不再一一介绍;感
兴趣可以访问www.cplusplus.com自行查阅相关内容。
STL - 容器 (Container) - 二元组 (pair)
* 二元组 (pair):用于存储二元组 (x,y)(并且 x,y 类型可以不相同)
#include <algorithm> // pair 声明 pair<int, int> a; // 声明一个二元组 a,用尖括号括起来 pair<int, int> b(3, 4); // 声明一个二元组 b, x=3, y=4 typedef pair<int, int> PI; // 使用类型定义 PI c(5, 6); // 声明一个二元组 c // pair 访问 int x = c.first, y = c.second; // x = 5, y = 6 PI d = c; // 相同类型的二元组可以直接赋值 c = PI(7, 8); // 重新赋值二元组 d = make_pair(9, 10); // 另一种赋值方式
* 二元组 (pair)的一个优点是可以直接比较大小;它会先比较第
一关键字(x),再比较第二关键字(y)。
可以自己定义cmp
PI arr[10]; for(int i=0; i<5; i++) arr[i] = PI(5 - i, i * i); sort(arr, arr+5); for(int i=0; i<5; i++) cout << "First␣element:" << arr[i].first << "␣" << "Second␣element:" << arr[i].second << endl; 输出结果: First element:1 Second element:16 First element:2 Second element:9 First element:3 Second element:4 First element:4 Second element:1 First element:5 Second element:0
* 通过二元组 (pair)可以把不同类型的元素给有机整合起来:
三元组:
typedef pair<int, PI> PII; // 定义三元组 PII p = PII(2, PI(4, 8)); // 嵌套定义三元组 cout << p.first << "," << p.second.first << "," << p.second.second << endl; // 嵌套输出 typedef pair<string, int> People; // 定义字符串 -整数二元组 People pa("Edward", 16); People pb("Bob", 17); if(pa > pb) swap(pa, pb); // 比较大小 cout << pa.first << ":" << pa.second << endl; // 输出较小值
STL - 容器 (Container) - 集合 (set)
* 在集合 (set)中,可以像普通的集合一样,保存所有不同的数:
set<int> S; // 定义一个整型类型的 set for(int i=0; i<10; i++) S.insert(i*i); // 把 0-9 的平方数加入集合中 set<int>::iterator p; // iterator:迭代器,相当于一个指针 p = S.find(4); // 指针 -- 找到 4 所在位置 cout << *p << endl; // 输出这个位置的值 -- 4 ++p; // 指针后移 cout << *p << endl; // 输出后一个平方数的值 -- 9
输出结果:
4
9
* 在集合 (set)中,可以支持查找一个数的位置:
p = S.find(5); // 假如我们想要找一个集合中没有的数 cout << "Notice␣:␣(5␣is␣not␣a␣square␣number)␣" << *p << endl; cout << (p == S.end()) << endl; // 就会返回一个特殊的指针:S.end() 结尾的指针 // C++ 中的容器都是左闭右开的: // S.begin() 头指针 - 存放数据,S.end() 尾指针 - 不存放数据 输出结果: Notice : (5 is not a square number) 10 1
如果要找的数不在集合里,输出集合里所有数的个数
如果输出一个条件的话,如果满足条件输出1,不满足输出0
* 在集合 (set)中,还有另一种方式查看一个数是否在集合中:~.count --> 判断某个值是否在数组中,如果在数组中为真,否则为假
for(int i=0; i<10; i++) if(S.count(i)) cout << i << "␣is␣an␣element␣of␣S." << endl; else cout << i << "␣is␣not␣an␣element␣of␣S." << endl; // count(x),如果 x 存在则返回 1,不存在则返回 0 输出结果: 0 is an element of S. 1 is an element of S. 2 is not an element of S. 3 is not an element of S. 4 is an element of S. 5 is not an element of S. 6 is not an element of S. 7 is not an element of S. 8 is not an element of S. 9 is an element of S.
* 在集合 (set)中,亦可以直接支持lower_bound 操作:~.delete() --> 删除某个数 ; ~.lower_bound() --> 寻找某个数
p = S.lower_bound(20); // 假如我们想要找一个集合中不小于 20 的数 cout << "The␣first␣element␣not␣lower␣than␣20:␣" << *p << endl; S.delete(p); // 删除一个数:使用指针的方式 p = S.lower_bound(20); // 再次寻找 cout << "The␣first␣element␣not␣lower␣than␣20:␣" << *p << endl; p = S.lower_bound(100); // 假如我们想要找一个集合中不小于 100 的数 cout << (p == S.end()) << endl; // 假如没有数比它大,则返回尾指针 输出结果: The first element not lower than 20: 25 The first element not lower than 20: 36 1
STL - 迭代器 (Iterator)
↓ 迭代器的运用:
vector<int>::iterator vi; // 定义迭代器,直接在后面加::iterator vector<int> V; // 定义容器 for(int i=1; i<10; i++) V.push_back(i * 3 - 2); // 新增值 for(vi = V.begin(); vi != V.end(); ++vi) cout << *vi << "␣"; cout << endl; // 按顺序输出容器中的值 // 特殊的迭代器:V.begin(), V.end()(左闭右开) // 迭代器可以自增:往后挪一位 // 不同容器的迭代器存在着区别 输出结果: 1 4 7 10 13 16 19 22 25
// STL 中每个容器都有对应的迭代器。 set<int> S; // 定义容器 set<int>::iterator p; // 定义迭代器 for(int i=0; i<10; i++) S.insert(i * i); // 插入平方数 p = S.begin(), ++p; S.erase(p); // 第一种删除方式(迭代器) :删除第二个元素 S.erase(49); // 第二种删除方式(值删除) :删除 49 cout << "The␣Sequence␣:␣"; for(p = S.begin(); p != S.end() ; ++p) cout << *p << "␣"; cout << endl; // 顺序输出 输出结果: The Sequence : 0 4 9 16 25 36 64 81
↑ 迭代器两种删除方式