首页 > 代码库 > STL——嗯~算详解(⊙_⊙)?
STL——嗯~算详解(⊙_⊙)?
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 = 4double 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 = 5double 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] = 2int p4 = lower_bound(a, a+8, 4) - a; // p4 = 5// a中最前的不比 4 小的元素是: a[5] = 4int p0 = lower_bound(a, a+8, 0) - a; // p0 = 0// a中最前的不比 0 小的元素是: a[0] = 1int 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=4typedef pair<int, int> PI; // 使用类型定义PI c(5, 6); // 声明一个二元组 c// pair 访问int x = c.first, y = c.second; // x = 5, y = 6PI 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:16First element:2 Second element:9First element:3 Second element:4First element:4 Second element:1First 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; // 定义一个整型类型的 setfor(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) 101
如果要找的数不在集合里,输出集合里所有数的个数
如果输出一个条件的话,如果满足条件输出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: 25The first element not lower than 20: 361
STL - 迭代器 (Iterator)
↓ 迭代器的运用:
vector<int>::iterator vi; // 定义迭代器,直接在后面加::iteratorvector<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); // 第二种删除方式(值删除) :删除 49cout << "The?Sequence?:?";for(p = S.begin(); p != S.end() ; ++p) cout << *p << "?";cout << endl; // 顺序输出输出结果:The Sequence : 0 4 9 16 25 36 64 81
↑ 迭代器两种删除方式
STL——嗯~算详解(⊙_⊙)?