STL——嗯~算详解(⊙_⊙)?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 = 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

迭代器两种删除方式

以上是关于STL——嗯~算详解(⊙_⊙)?的主要内容,如果未能解决你的问题,请参考以下文章

STL之list底层简单实现(七千字长文详解!)

STL-list实现(注释详解)

STL-list实现(注释详解)

STL-list实现(注释详解)

C++ STL详解

C++ STL详解