算法训练营 STL常用函数

常用函数

STL提供了一些常用函数,包含在头文件#include<algorithm>中。

  • min(x,y):求两个元素的最小值。
  • max(x,y):求两个元素的最大值。
  • swap(x,y):交换两个元素。
  • find(begin,end,x):返回指向区间[begin,end)第1个值为x的元素指针。如果没找到,则返回end
  • count(begin,end,x):返回指向区间[begin,end)值为x的元素数量,返回值为整数。
  • reverse(begin,end):翻转一个序列。
  • random_shuffle(begin,end):随机打乱一个序列。
  • unique(begin,end):将连续的相同元素压缩为一个原数,返回去重后的尾指针。不连续的相同元素不会被压缩,因此一般先排序后去重。
  • fill(begin,end,val):将区间[begin,end)的每个元素都设置为val
  • sort(begin,end,compare):对一个序列排序,参数beginend表示一个范围,分别为待排序的首地址和尾地址;compare表示排序的比较函数,可省略,默认为升序。stable_sort(begin,end,compare)为稳定排序,即保持相等元素的相对位置
  • nth_element(begin,begin+k,end,compare):使区间[begin,end)k小的元素处在第k个位置上,左边元素都小于或等于它,右边元素都大于或等于它,但并不保证其他元素有序。
  • lower_bound(begin,end,x)/upper_bound(begin,end,x):两个函数都是利用二分查找的方法,在有序数组中查找第1个满足条件的元素,返回指向该元素的指针。
  • next_permutation(begin,end)/pre_permutation(begin,end)next_permutation()是求按字典序的下一个排列的函数,可以得到全排列。pre_permutation()是求按字典序的上一个排列的函数。

部分函数详解

sort(begin,end,compare)

  1. 使用默认的函数排序。
int main(){
	int a[4] = {7,4,5,23};
	sort(a,a+4);//数组a按升序排序
	for(int i = 0; i<4; i++){
		cout << a[i] << " ";
	}
	return 0;
}
  1. 自定义比较函数。
bool cmp(int a, int b){//比较函数
	return a<b;//升序排列,如果改为return a>b,则为降序
}
int main(){
	int a[4] = {7,4,5,23};
	sort(a,a+4,cmp);//数组a按升序排序
	for(int i = 0; i<4; i++){
		cout << a[i] << " ";
	}
	return 0;
}
  1. 利用functional标准库,引入头文件#include<functional>functional提供了一些基于模板的比较函数对象。
  • equal_to<Type>:等于。
  • not_equal_to<Type>:不等于。
  • greater<Type>:大于。
  • greater_equal<Type>:大于或等于。
  • less<Type>:小于。
  • less_equal<Type>:小于或等于。
  • 升序:sort(begin,end,less<data-type>())
  • 降序:sort(begin,end,greater<data-type>())
int main(){
	int a[4] = {7,4,5,23};
	sort(a,a+4,greater<int>());//数组a按升序排序
	for(int i = 0; i<4; i++){
		cout << a[i] << " ";
	}
	return 0;
}

nth_element(begin,begin+k,end,compare)

当省略最后一个参数时,该函数使区间[begin,end)kk从0开始)小的元素处在第k个位置上。当最后一个参数为greater<int>()时,改函数使区间[begin,end)第k大的元素处在第k个位置上。特别注意:在函数执行后会改变原序列,但不保证其他元素有序。

void print(int a[], int n){
	for(int i = 0; i<n; i++){
		cout << a[i] << " ";
	}
	cout << endl;
}
int main(){
	int a[7] = {6,2,7,4,20,15,5};
	nth_element(a,a+2,a+7);
	print(a,7);
	int b[7] = {6,2,7,4,20,15,5};
	nth_element(b,b+2,b+7,greater<int>());
	print(b,7);
	return 0;
}

输出:

4 2 5 6 20 15 7	//第2小的数5在第2个位置上
15 20 7 6 4 5 2 //第2大的数7在第2个位置上

lower_bound()/upper_bound()

lower_bound()upper_bound()都是用二分查找的方法在一个有序数组中查找第1个满足条件的元素。

  1. 在从小到大的排序数组中
  • lower_bound(begin,end,x):从数组的begin位置到end-1位置二分查找第1个大于或等于x的元素,找到后返回该元素的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到元素在数组中的下标。
  • upper_bound(begin,end,x):从数组的begin位置到end-1位置二分查找第1个大于x的元素,找到后返回该元素的地址,不存在则返回end
  1. 在从大到小的排序数组中
  • lower_bound(begin,end,x,greater<type>()):从数组的begin位置到end-1位置二分查找第1个小于或等于x的元素,找到后返回该元素的地址,不存在则返回end
  • upper_bound(begin,end,x,greater<type>()):从数组的begin位置到end-1位置二分查找第1个小于x的元素,找到后返回该元素的地址,不存在则返回end
void print(int a[], int n){
	for(int i = 0; i<n; i++){
		cout << a[i] << " ";
	}
	cout << endl;
}
int main(){
	int a[6] = {6,2,7,4,20,15};
	sort(a,a+6);//从小到大排序
	print(a,6);
	int pos1 = lower_bound(a,a+6,7)-a;//返回数组中第1个大于或等于7的元素下标
	int pos2 = upper_bound(a,a+6,7)-a;//返回数组中第1个大于7的元素下标
	cout << pos1 << " " << a[pos1] << endl;
	cout << pos2 << " " << a[pos2] <<endl;
	sort(a,a+6,greater<int>());从大到小排序
	print(a,6);
	int pos3 = lower_bound(a,a+6,7,greater<int>())-a;//返回第1个小于或等于7的元素下标
	int pos4 = upper_bound(a,a+6,7,greater<int>())-a;//返回第1个小于7的元素下标
	cout <<pos3 << " "<<a[pos3] <<endl;
	cout << pos4 <<" "<<a[pos4] <<endl;
	return 0;
}

next_permutation()/pre_permutation()

next_permutation()是求按字典序排序的下一个排列的函数,可以得到全排列。pre_permutation()是求按字典序排序的上一个排列的函数。

  1. int类型的next_permutation()
int main(){
	int a[3] = {1,2,3};
	do{
		for(int i = 0; i<3; i++){
			cout << a[i] << " ";
		}
		cout << endl;
	}while(next_permutation(a,a+3));
	//如果存在a之后的排列,就返回true
	//如果a是最后一个排列且没有后继,则返回false
	//每执行一次,a就编程它的后继
	return 0}

输出:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

如果改成while(next_permutation(a,a+2)),即只对前2个元素进行字典序排序。输出:

1 2 3
2 1 3

若排列本来就最大,且没有后继,则在next_permutation执行后,对排列进行字典升序排序,相当于循环。.

int list[3] = {3,2,1};
next_permutation(list,list+3);
cout << list[0] << " " << list[1] << " " << list[2] << " " <<endl;
  1. char类型的next_permutation()
int main(){
	char ch[205];
	cin >> ch;
	sort(ch,ch+strlen(ch));//该语句对输入的数组进行字典升序排序
	//例如输入“9874563102 out << ch;”,则将输出“0123456789”,这样就能输出全排列
	char *first= ch
	char *last= ch + strlen(ch);
	do{
		cout << ch <<endl;
	}while(next_permutation(first,last));
}
	return 0;
  1. char类型的next_permutation()
int main(){
	string s;
	while(cin >> s && s!= "#"){
		sort(s.begin(),s.end());//全排列
		cout << s << endl;
		while(next_permutation(s.begin(),s.end())){
			cout << s << endl;
		}
		return 0;
	}
}
  1. 自定义优先级的next_permutation
int cmp(char a,char b){//A<a<B<b<...<Z<z
	if(tolower(a) != tolower(b)){
		return tolower(a)<tolower(b);
	}
	else{
		return a<b;
	}
}
sort(ch,ch+strlen(ch),cmp);
do{
	printf("%s\n",ch);
}while(next_permutation(ch, ch+strlen(ch), cmp))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

羽星_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值