STL(standard template library)标准模板库
STL(标准模板库),是目前C++内置支持的library。它的底层利用了C++类模板和函数模板的机制,由三大部分组成:容器、算法和迭代器。
目前STL有六大组件
容器 container
算法 algorthm
迭代器 iterator
仿函数 function object
适配器 adaptor
空间配置器 allocator
算法
二分查找
C++ lower_bound 与 upper_bound 函数
需要头文件:
#include <algorithm>
二分查找的函数有 3 个:
lower_bound(first, last, &val) 算法返回一个非递减序列 [first, last) 中第一个大于等于值 val 的位置;
upper_bound(first, last, &val) 算法返回一个非递减序列 [first, last) 中第一个大于值 val 的位置;
binary_search(first, last, &val) 算法返回一个非递减序列 [first, last) 中是否存在这么一个数,是一个bool值。
std::lower_bound()
功能:函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置,该位置越界
lower_bound()源码:
int lower_bound(int *array, int size, int key) {
int first = 0, middle; //这种操作?
int half, len;
len = size;
while(len > 0) {
half = len >> 1; //右移操作,len大小减半
middle = first + half;
if(array[middle] < key) { //在右半序列继续查找
first = middle + 1;
len = len - half - 1 ;
} else //在左半序列继续查找
len = half;
}
return first;
}
std::upper_bound()
功能:函数upper_bound()返回的在前闭后开区间查找的关键字的上界,返回大于val的第一个元素位置
注意:返回查找元素的最后一个可安插位置,也就是“元素值>查找值”的第一个元素的位置。同样,如果val大于数组中全部元素,返回的是last。(注意:数组下标越界)
upper_bound()源码:
int upper_bound(int *array, int size, int key) {
int len = size - 1;
int half, middle;
while(len > 0) {
half = len >> 1;
middle = first + half;
if(array[middle] > key) //在左半序列继续查找
len = half;
else { //在右半序列继续查找
first = middle + 1;
len = len - half - 1;
}
}
return first;
}
例子:
void main()
{
vector<int> t;
t.push_back(1);
t.push_back(2);
t.push_back(3);
t.push_back(4);
t.push_back(6);
t.push_back(7);
t.push_back(8);
int low=lower_bound(t.begin(),t.end(),5)-t.begin();
int upp=upper_bound(t.begin(),t.end(),5)-t.begin();
cout<<low<<endl;
cout<<upp<<endl;
system("pause");
}
结构体例子
#include <cstdio>
#include <algorithm>
using namespace std;
int n,m;
struct WORK
{
int d,p;
bool operator <(const WORK x)
{
if(x.d==d)return x.p>p;
return x.d>d;
}
}work[100010];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d%d",&work[i].d,&work[i].p);
sort(work+1,work+n+1);
for(int i=1;i<=n;i++)
printf("%d %d\n",work[i].d,work[i].p);
int ab;
for(int i=1;i<=m;i++)
{
scanf("%d",&ab);printf("ab=%d\n");
work[0].d=ab;work[0].p=1000000001;
int temp = lower_bound(work+1,work+n+1,work[0])-work;
printf("temp=%d\n",temp);
if(temp-1>0)
printf("%d\n",work[temp-1].p);
else
printf("0\n");
}
return 0;
}
如果使用结构体,要自己在结构体里重载比较符。要注意,如果数据结构存储的东西是从1到n而不是0到n-1的话,减下标时要+1。
排序
sort()类函数
函数名 | 功能描述 |
---|---|
sort | 对给定区间所有元素进行排序 |
stable_sort | 对给定区间所有元素进行稳定排序 |
partial_sort | 对给定区间所有元素部分排序 |
partial_sort_copy | 对给定区间复制并排序 |
nth_element | 找出给定区间的某个位置对应的元素 |
is_sorted | 判断一个区间是否已经排好序 |
partition | 使得符合某个条件的元素放在前面 |
stable_partition | 相对稳定的使得符合某个条件的元素放在前面 |
需要头文件:
#include <algorithm>
std::sort()
语法描述:sort(begin,end,cmp),cmp参数可以没有,如果没有默认非降序排序。
基本数据类型排序
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
int a[5]={1,3,4,2,5};
sort(a,a+5);
for(int i=0;i<5;i++)
cout<<a[i]<<' ';
return 0;
}
输出:
1 2 3 4 5
因为没有cmp函数,默认非降序排序。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int a[5]={1,3,4,2,5};
sort(a,a+5,cmp);
for(int i=0;i<5;i++)
cout<<a[i]<<' ';
return 0;
}
输出:
5 4 3 2 1
对于基本数据类型来说(类型支持“<”、“>”等比较运算符),是有现成的模板函数的。
equal_to、not_equal_to、greater、greater_equal、less、less_equal。
升序:sort(begin,end,less<data-type>());
降序:sort(begin,end,greater<data-type>());
#include<iostream>
#include<algorithm>
using namespace std;
int main ( )
{
int a[20]={2,4,1,23,5,76,0,43,24,65},i;
for(i=0;i<20;i++)
cout<<a[i]<<" ";
cout<<endl;
sort(a,a+20,greater<int>());//这里的greater是带括号的,cmp的不带的
for(i=0;i<20;i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
输出:
2 4 1 23 5 76 0 43 24 65 0 0 0 0 0 0 0 0 0 0
76 65 43 24 23 5 4 2 1 0 0 0 0 0 0 0 0 0 0 0
STL容器类型排序
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main ( )
{
int i,temp[]={2,4,1,23,5,76,0,43,24,65};
vector<int> a(temp,temp+10);//用数组初始化vector
for(i=0;i<a.size();i++)
cout<<a[i]<<" ";
cout<<endl;
sort(a.begin(),a.end());
for(i=0;i<a.size();i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
输出
2 4 1 23 5 76 0 43 24 65
0 1 2 4 5 23 24 43 65 76
使用反向迭代器来逆向排序
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main ( )
{
int i,temp[]={2,4,1,23,5,76,0,43,24,65};
vector<int> a(temp,temp+10);//用数组初始化vector
for(i=0;i<a.size();i++)
cout<<a[i]<<" ";
cout<<endl;
sort(a.rbegin(),a.rend());
for(i=0;i<a.size();i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
输出
2 4 1 23 5 76 0 43 24 65
76 65 43 24 23 5 4 2 1 0
对于自定义数据类型有两种使用方法
使用cmp函数
#include <cstdio>
#include <algorithm>
using namespace std;
int n;
struct WORK
{
int d,p;
}work[100010];
bool cmp(WORK x,WORK y)
{
return x.d<y.d;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&work[i].d,&work[i].p);
sort(work+1,work+n+1,cmp);
return 0;
}
数据结构内重载比较符
#include <cstdio>
#include <algorithm>
using namespace std;
int n;
struct WORK
{
int d,p;
bool operator <(const WORK x)
{
if(x.d==d)return x.p>p;
return x.d>d;
}
}work[100010];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&work[i].d,&work[i].p);
sort(work+1,work+n+1);
return 0;
}
std::unique()
去重函数
需要头文件:
#include <algorithm>
unique函数属于STL中比较常用函数,它的功能是元素去重。并不是真的删除,而是将后面的不重复元素放到前面来。去重的数据结构不一定要有序,由此可见,该函数必定是扫一遍并对每个数做点什么,如用平衡二叉树实现的话,复杂度可到O(nlog),暴力的话为O(n²)。但是具体怎么实现的我不知道。
函数原型
iterator unique(iterator it_1,iterator it_2);
iterator unique(iterator it_1,iterator it_2,bool cmp);
对两迭代器 [it_1,it_2) 前闭后开区间内的数进行去重,可以自定义cmp相等函数
例子
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int a[10] = { 0, 7, 7, 6, 1, 1, 5, 5, 8, 9 };
int n = unique(a, a + 10) - a;//记住返回的是末尾迭代器而不是数组长度
cout << n << endl; // 7
for (int i = 0; i < 10; i++)
cout << a[i] << " "; // 0 7 6 1 5 8 9 5 8 9
for (int i = 0; i < n; i++)
cout << a[i] << " "; // 0 7 6 1 5 8 9
return 0;
}
配合STL用法
#include <iostream> // std::cout
#include <algorithm> // std::unique, std::distance
#include <vector> // std::vector
bool myfunction (int i, int j) {
return (i==j);
}
int main () {
int myints[] = {10,20,20,20,30,30,20,20,10}; // 10 20 20 20 30 30 20 20 10
std::vector<int> myvector (myints,myints+9);
// using default comparison:
std::vector<int>::iterator it;
it = std::unique (myvector.begin(), myvector.end()); // 10 20 30 20 10 ? ? ? ?
// ^
myvector.resize( std::distance(myvector.begin(),it) ); // 10 20 30 20 10
// using predicate comparison:
std::unique (myvector.begin(), myvector.end(), myfunction); // (no changes)
// print out content:
std::cout << "myvector contains:";
for (it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
输出:
myvector contains: 10 20 30 20 10
算法模板:
链接: https://pan.baidu.com/s/17lrYgvBv7x_FAb8GXFTz8Q 提取码: 49ge