标准模板库(STL)四:STL算法之变值/变序/排序/有序区间/合并

变序算法

  • 变序算法改变容器中元素的顺序
  • 但是不改变元素的值
  • 变序算法不适用于关联容器
  • 算法复杂度大部分都是 O ( n ) O(n) O(n)
算法功能
reverse颠倒区间的前后次序
reverse_copy把一个区间颠倒后的结果拷贝到另一个区间, 源区间不变
rotate将区间进行循环左移
rotate_copy将区间以首尾相接的形式进行旋转后的结果 拷贝到另一个区间,源区间不变
next_permutation将区间改为下一个排列(可自定义比较器)
prev_permutation将区间改为上一个排列(可自定义比较器)
random_shuffle随机打乱区间内元素的顺序
partition把区间内满足某个条件的元素移到前面,不满足该 条件的移到后面
stable_partition
  • 把区间内满足某个条件的元素移到前面
  • 不满足该条件的移到后面
  • 而对这两部分元素, 分别保持它们原来的先后次序不变
random_shuffle

原型

template<class RanIt>
void random_shuffle(RanIt first, RanIt last);
  • 随机打乱[first,last) 中的元素, 适用于能随机访问的容器
reverse

原型

template<class BidIt>
void reverse(BidIt first, BidIt last);
  • 颠倒区间[first,last)顺序
next_permutation

原型

template<class InIt> 
bool next_permutaion (Init first,Init last);
  • 求下一个排列

示例

#include <iostream>
#include <algorithm>
#include <string>
using namespace std;

int main()
{
	string str = "231";
	char szStr[] = "324";
	while (next_permutation(str.begin(), str.end()))//参数为起点,终点
	{
		cout << str << endl;//312,321
	}
	cout << "****" << endl;
	while (next_permutation(szStr, szStr + 3))
	{
		cout << szStr << endl;
	}
	sort(str.begin(), str.end());
	cout << "****" << endl;
	while (next_permutation(str.begin(), str.end()))
	{
		cout << str << endl;
	}
	return 0;
}

next_permutation不单单可以用在数字上,也可以用在自定义的数据类型上

using namespace std;
int main() {
	int a[] = {8,7,10};
	list<int>ls(a, a + 3);
	while (next_permutation(ls.begin(), ls.end())) {
		list<int>::iterator i;
		for (i + ls.begin; i != ls.end(); i++) {
			cout << *i << " ";
			cout << endl;
		}
	}
}

排序算法

  • 比前面的变序算法复杂度更高, 一般是 O ( n log ⁡ ( n ) ) O(n\log(n)) O(nlog(n))
  • 排序算法需要随机访问迭代器的支持
  • 不适用于关联容器和list(list是双向迭代器,要使用list::sort)
算法功能
sort将区间从小到大排序(可自定义比较器)
stable_sort将区间从小到大排序, 并保持相等元素间的相对次序(可自定义比较器)
partial_sort对区间部分排序, 直到最小的n个元素就位(可自定义比较器)
partial_sort_copy将区间前n个元素的排序结果拷贝到别处, 源区间不变(可自定义比较器)
nth_element对区间部分排序, 使得第n小的元素(n从0开始算)就位, 而且比 它小的都在它前面, 比它大的都在它后面(可自定义比较器)
make_heap使区间成为一个“堆”(可自定义比较器)
push_heap将元素加入一个是“堆”区间(可自定义比较器)
pop_heap从“堆”区间删除堆顶元素(可自定义比较器)
sort_heap将一个“堆”区间进行排序,排序结束后,该区间就是普 通的有序区间,不再是 “堆”了(可自定义比较器)
sort

原型1

template<class RanIt>
void sort(RanIt first, RanIt last);
  • 按升序排序
  • 没有自定义比较器时,判断x是否应比y靠前, 就看 x < y 是否为true

原型2

template<class RanIt, class Pred>
void sort(RanIt first, RanIt last, Pred pr);
  • 按升序排序
  • 判断x是否应比y靠前, 就看 pr(x,y)是否为true,此时pr为函数对象或函数指针

sort 实际上是快速排序, 时间复杂度 $O(n\log(n)) $

  • 平均性能最优
  • 但是最坏的情况下, 性能可能非常差 O ( n 2 ) O(n^2) O(n2)

如果要保证 “最坏情况下” 的性能, 那么可以使用 stable_sort

  • stable_sort实际上是归并排序, 特点是能保持相等元素之间的先后次序
  • 在有足够存储空间的情况下, 复杂度为 n log ⁡ ( n ) n\log(n) nlog(n), 否则复杂度为 n log ⁡ ( n ) log ⁡ ( n ) n\log(n)\log(n) nlog(n)log(n)
  • stable_sort 用法和 sort
    同。
#include<algorithm>
#include<iostream>
#include<string>

using namespace std;
class MyLess {
public:
	bool operator() (int n1, int n2) {
		return (n1 % 10) < (n2 % 10);
	}
};
class MyGreater {
public:
	bool operator() (int n1, int n2) {
		return n1 > n2;
	}
};
int main() {
	int a[] = { 14,2,9,111,78 };
	sort(a, a + 5, MyLess());
	int i;
	for (i = 0; i < 5; i++) {
		cout << a[i] << " ";
	}
	cout << endl;
	sort(a, a + 5, greater<int>());
	for (i = 0; i < 5; i++)
		cout << a[i] << " ";
	cout<<endl;
	sort(a,a+5,MyGreater());
	for (i = 0; i < 5; i++)
		cout << a[i] << " ";
}

输出结果如下:

111 2 14 78 9 //按个位数比大小
111 78 14 9 2 //系统自带greater
111 78 14 9 2 //自己定义greater

有序区间算法

  • 要求所操作的区间是已经从小到大排好序的
  • 需要随机访问迭代器的支持
  • 有序区间算法不能用于关联容器和list
算法功能
binary_search判断区间中是否包含某个元素
此处的相等是==,体现在程序里是x<y,y<x同时不成立
includes判断是否一个区间中的每个元素,都在另一个区间中
lower_bound查找最后一个不小于某值的元素的位置
upper_bound查找第一个大于某值的元素的位置
equal_range同时获取lower_bound和upper_bound
merge合并两个有序区间到第三个区间
set_union将两个有序区间的并拷贝到第三个区间,允许有重复元素
set_intersection将两个有序区间的交拷贝到第三个区间
set_difference将两个有序区间的差拷贝到第三个区间
set_symmetric_difference将两个有序区间的对称差拷贝到第三个区间KaTeX parse error: Expected 'EOF', got '\or' at position 2: A\̲o̲r̲ ̲B-A\and B
inplace_merge将两个连续的有序区间原地合并为一个有序区间
binary_search
  • 折半查找
  • 要求容器已经有序且支持随机访问迭代器, 返回是否找到bool

原型1

template<class FwdIt, class T>
  bool binary_search(FwdIt first, FwdIt last, const T& val);
  • 比较两个元素x, y 大小时, 看 x < y

原型2

template<class FwdIt, class T, class Pred>
bool binary_search(FwdIt first, FwdIt last, const T& val, Pred pr);
  • 比较两个元素x, y 大小时, 若 pr(x,y) 为true, 则 认为x小于y
lower_bound
template<class FwdIt, class T>
FwdIt lower_bound(FwdIt first, FwdIt last, const T& val);
  • 要求[first,last)是有序的
  • 查找[first,last)中的, 最大的位置 FwdIt, 使得[first,FwdIt) 中所有的元素都比 val 小
equal_range
template<class FwdIt, class T>
pair<FwdIt, FwdIt> equal_range(FwdIt first, FwdIt last, const T& val);
  • 要求[first,last)是有序的
  • 返回值是一个pair, 假设为 p, 则:
    • [first,p.first) 中的元素都比 val 小
    • [p.second,last)中的所有元素都比 val 大
    • p.first 就是lower_bound的结果
    • p.last 就是 upper_bound的结果

merge

  • 把[first1,last1), [ first2,last2) 两个升序序列合并, 形成第 3 个升序序列, 第3个升序序列以 x 开头

原型1

template<class InIt1, class InIt2, class OutIt>
OutIt merge(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x);
  • 用 < 作比
    较器

原型2

template<class InIt1, class InIt2, class OutIt, class Pred>
OutIt merge(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x, Pred pr);
  • 用 pr 作比较器
includes
template<class InIt1, class InIt2> 
bool includes(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2);
template<class InIt1, class InIt2, class Pred> 
bool includes(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, Pred pr);

判断[First2, last2)中的每个元素,是否都在[First1,last1)中:

  • 第一个用<作为比较器,x<y,y<x都不成立
  • 第二个用pr, pr(x,y)==true说明x,y相等
set_difference
  • 求出[first1,last1)中, 不在[first2,last2)中的元素, 放到从 x 开始的地方
  • 如果 [first1,last1) 里有多个相等元素不在[first2,last2)中, 则这多个元素也都会被放入x代表的目标区间里
template<class InIt1, class InIt2, class OutIt>
OutIt set_difference(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x);
template<class InIt1, class InIt2, class OutIt, class Pred> 
OutIt set_difference(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt x, Pred pr);
set_intersection
  • 求出[first1,last1)和[first2,last2)中共有的元素, 放到从x开始的 地方
  • 若某个元素e 在[first1,last1)里出现 n1次, 在[first2,last2)里出 现n2次, 则该元素在目标区间里出现min(n1,n2)次
set_union
  • 求两个区间的并, 放到以 x开始的位置
  • 若某个元素e 在[first1,last1)里出现 n1次, 在[first2,last2)里 出现n2次, 则该元素在目标区间里出现max(n1,n2)次

Reference

https://www.coursera.org/learn/cpp-chengxu-sheji/

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值