algorithm意为"算法",是C++的标准模版库(STL)中最重要的头文件之一,提供了大量基于迭代器的非成员模板函数。
- 类 别 C++标准库
- 头文件
#include <algorithm>
- 命名空间 using namespace std
其中包括以下部分函数:
- max()、min()和abs()
- swap()
- reverse()
- next_permutation()
- fill()
- sort()
- lower_bound()和upper_bound()
- 最大最小操作
max | 返回两个元素中值最大的元素 |
min | 返回两个元素中值最小的元素 |
abs() | 返回元素绝对值 |
next_permutation | 返回给定范围中的元素组成的下一个按字典序的排列 |
- 修改内容操作
swap | 交换两个对象的值 |
reverse | 反转排序指定范围中的元素 |
fill | 将一个范围的元素赋值为给定值 |
- 排序操作
sort | 排序 |
- 查找操作
lower_bound | 返回指向范围中第一个值大于或等于给定值的元素的迭代器 |
upper_bound | 返回指向范围中第一个值大于给定值的元素的迭代器 |
- max()
作 用:返回一个最大数值
语 法:MAX(number1,number2,…)
参 数: Number1,number2,
注意: 如果参数不包含数字,函数 MAX 返回 0。
示例
示例1:如果 A1:A5 包含数字 10、7、9、27 和 2,则:
MAX(A1:A5) 等于 27
MAX(A1:A5,30) 等于 30
示例2:如果A1=71、A2=83、A3=76、A4=49、A5=92、A6=88、A7=96。
则公式“=MAX(A1:A7)”返回96。
#include <iostream>
#include <algorithm>
using namespace std;
int main () {
cout << "max(1,2)==" << std::max(1,2) << '\n';
cout << "max(2,1)==" << std::max(2,1) << '\n';
cout << "max('a','z')==" << std::max('a','z') << '\n';
cout << "max(3.14,2.73)==" << std::max(3.14,2.73) << '\n';
return 0;
}
- min()
min(x,y)分别返回x和y中的最小值,且参数必须是两个。
示例1:如果 A1:A5 中依次包含数值 10,7,3,27 和 2,那么
MIN(A1:A5) 等于 2
MIN(A1:A5, 0) 等于 0
例:
#include <iostream>
#include <algorithm>
using namespace std;
int main () {
cout << "min(1,2)==" << min(1,2) << '\n';
cout << "min(2,1)==" << min(2,1) << '\n';
cout << "min('a','z')==" << min('a','z') << '\n';
cout << "min(3.14,2.72)==" << min(3.14,2.72) << '\n';
return 0;
}
- abs()
abs(x) 返回x的绝对值。x必须为整数,浮点型的绝对值要用math头文件下的fabs
//#include<algorithm>
#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
int main()
{
int x,f;
printf("请输入一个整数:\n");
scanf("%d",&x);
printf("绝对值为%d\n",abs(x));
// printf("请输入一个浮点数:\n");
// scanf("%lf",&f);
// printf("绝对值为%lf\n",fabs(f));
return 0;
}
如果没有头文件,绝对值返回0
- swap()
交换两个对象的值,即交换a和b的值。
通用的函数交换模板
template<class T> void swap(T &a,T &b) { T c(a); a=b; b=c; }
针对int类型的优化
void swap(int &a,int &b)
{
a^=b;
b^=a; //相当于b=a
a^=b; //相当于a=b
}
自定义swap时,注意事项
1.无法实现交换目的
void swap(int a,int b)//这里只是交换了a和b实参的副本,而它们本身没有交换。
{
int temp=a;
a=b;
b=temp;
}
2.能够达到交换目的
#include <iostream>
#include <algorithm>
using namespace std;
void swap(int *a,int *b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}
//使用
int main()
{
int a=1,b=2;
swap(&a,&b);
cout<<a<<endl;
cout<<=<<endl;
return 0;
}
- reverse()
1.会将区间内的元素全部逆序。常用于数组,字符串,容器等,其本身的函数参数也不复杂。
2.容器类型的要用begin()和end()来指定反转的区域,数组类型的直接用int类型即可。
3.reverse函数用于反转在[first,last)范围内的顺序(包括first指向的元素,不包括last指向的元素),reverse函数没有返回值
此函数模板的行为等效于(通过调用iter_swap来交换元素位置):
template <class BidirectionalIterator>
void reverse (BidirectionalIterator first, BidirectionalIterator last)
{
while ((first!=last)&&(first!=--last)) {
std::iter_swap (first,last);
++first;
}
}
- 交换vector容器中元素的顺序
vector<int> v = {5,4,3,2,1};
reverse(v.begin(),v.end());//v的值为1,2,3,4,5
- string类的字符串
string str="www.mathor.top";
reverse(str.begin(),str.end());//str结果为pot.rohtam.wwww
例
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[50];
int b[50];
for(int i=0;i<10;i++)
{
a[i]=i;
if(i!=9)
cout<<a[i]<<" ";
else
cout<<a[i]<<endl;
}
reverse(a,a+10); //第二个参数是数组最后一个元素的下一个地址
for(int i=0;i<10;i++)
{
if(i!=9)
cout<<a[i]<<" ";
else
cout<<a[i]<<endl;
}
}
- next_permutation()
返回给定范围中的元素组成的下一个按字典序的排列,next_permutation(start,end)和prev_permutation(start,end)。这两个函数作用是一样的,区别就在于前者求的是当前排列的下一个排列,后一个求的是当前排列的上一个排列。
next_permutation函数,其函数原型为:
#include <algorithm>
bool next_permutation(iterator start,iterator end)//当当前序列不存在下一个排列时,函数返回false,否则返回true
- 当把while(next_permutation(num,num+3))中的3改为2时,输出就变为了:只对1,2进行全排,可以知道next_permutation(num,num+n)函数是对数组num中的前n个元素进行全排列,同时并改变num数组的值。
- 还有next_permutation()在使用前需要对欲排列数组按升序排序,否则只能找出该序列之后的全排列数。比如,如果数组num初始化为2,3,1,那么输出就变为了:
- 此外,next_permutation(node,node+n,cmp)可以对结构体num按照自定义的排序方式cmp进行排序。也可以对字符next_permutation 自定义比较函数
若排列本米就是最大的了没有后继,则next permotation执行后,会对
排列进行字典开序排序相当于循环
int list[31={3.,2.1};
next permutation(list,list+3);
conut<<list[0]<<" "<list[U<<" "<listl2k<<endl;//输出:1 2 3
- List item
char类型的next permutation
//
该语句对输入的数组进行字典升序排序如输入9874563102 cout<<ch;
将输出 0123456789这样就能输出全排列了
int mainO
char ch[2051;cin>> ch;
sort(ch, ch+ strlen(ch));
//这样就不必事先知道ch的大小了,是把整个ch字符串全都进行排序
//若采用while(nextpermutation(ch,ch+5);如果只输入1562,就会产
生错误,因为ch中第五个元素指向未知
//若要整个字符中进行排序,参数5指的是数组的长度,不含结束符
char *frstE ch;
char *last ch+ strlen(ch);
do{
cout<<ch<< endl;
}while(next permutation(first,lastD);return0;
- string类型的nextpermutation
int main()
{
string line;
while(cin>>line&&line!="#"')
{
if(nexL permutation(line.beginQline.end0)当前输入位置开始
cout<line<<endl;
elsecout<< "Nosuccesor\";
}
}
int main()
{
string line;
while(cin> >line&line!= "#")
{
sort(line.begin(),line.end0);/排列cout< dline<<endl;
}
}
例
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int num[3]={1,2,3};
do
{
cout<<num[0]<<" "<<num[1]<<" "<<num[2]<<endl;
}
while(next_permutation(num,num+3));
return 0;
}
- fill()
1.按照单元赋值,将一个区间的元素都赋同一个值
2.fill(arr, arr + n, 要填入的内容);
fill(vector.begin(), vector.end(), val);
3.
#include <cstdio>
#include <algorithm>
using namespace std;
int main() {
int arr[10];
fill(arr, arr + 10, 2);
return 0;
}
4.vector容器
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
int main()
{
vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
fill(v.begin(), v.end(), -1);
return 0;
}
例
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main () {
vector<int> myvector (8);// myvector: 0 0 0 0 0 0 0 0
fill (myvector.begin(),myvector.begin()+4,5);
// myvector: 5 5 5 5 0 0 0 0
fill (myvector.begin()+3,myvector.end()-2,8);
// myvector: 5 5 5 8 8 8 0 0
cout << "myvector contains:";
for (vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
cout << " " << *it;
cout << endl;
return 0;
}
- sort()
1.Sort函数有三个参数:
(1)第一个是要排序的数组的起始地址。
(2)第二个是结束的地址(最后一位要排序的地址的下一地址)
(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。
2.Sort函数使用模板:Sort(start,end,排序方法)
//例一:sort函数没有第三个参数,实现的是从小到大
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[10]={9,6,3,8,5,2,7,4,1,0};
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
sort(a,a+10);
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
return 0;
}
//例2需要在sort()函数里的第三个参数里,从大到小排序!
//加入一个比较函数compare(),
#include<iostream>
#include<algorithm>
using namespace std;
bool compare(int a,int b)
{
return a>b;
}
int main()
{
int a[10]={9,6,3,8,5,2,7,4,1,0};
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
sort(a,a+10,compare);//在这里就不需要对compare函数传入参数了,
//这是规则
for(int i=0;i<10;i++)
cout<<a[i]<<endl;
return 0;
}
- lower_bound()和upper_bound( )
lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。
一、lower_bound()
- lower_bound()返回值是一个迭代器,返回指向比key大的第一个值的位置
对象:有序数组或容器 - lower_bound(起始地址,结束地址,要查找的数值) 返回的是数值 第一个 出现的位置。
- 功能:函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置.
注意:如果所有元素都小于val,则返回last的位置,且last的位置是越界的!!
二、upper_bound()
- upper_bound(起始地址,结束地址,要查找的数值) 返回的是数值 最后一个 出现的位置。
- 功能:函数upper_bound()返回的在前闭后开区间查找的关键字的上界,返回大于val的第一个元素位置
注意:返回查找元素的最后一个可安插位置,也就是“元素值>查找值”的第一个元素的位置。同样,如果val大于数组中全部元素,返回的是last。(注意:数组下标越界)
例
#include <iostream>
#include <algorithm>
#include<vector>
using namespace std;
int 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;
return 0;
}