C++篇——stl算法函数总概

stl算法类别

• 不变序列算法
• 变值算法
• 删除算法
• 变序算法
• 排序算法
• 有序区间算法
• 数值算法

大多重载的算法都是有两个版本的
• 用 “==” 判断元素是否相等, 或用 “<” 来比较大小
• 多出一个类型参数 “Pred” 和函数形参 “Pred op” :
通过表达式 “op(x,y)” 的返回值: ture/false
判断x是否 “等于” y,或者x是否 “小于” y
如下面的有两个版本的min_element:
iterator min_element(iterator first, iterator last);
iterator min_element(iterator first, iterator last, Pred op);

不变序列算法

  • 该类算法不会修改算法所作用的容器或对象
  • 适用于顺序容器和关联容器
  • 时间复杂度都是O(n)
min 					求两个对象中较小的(可自定义比较器)
max 					求两个对象中较大的(可自定义比较器)
min_element   			求区间中的最小值(可自定义比较器)
max_element   			求区间中的最大值(可自定义比较器)
for_each 				对区间中的每个元素都做某种操作
count 					计算区间中等于某值的元素个数
count_if 				计算区间中符合某种条件的元素个数
find 					在区间中查找等于某值的元素
find_if 				在区间中查找符合某条件的元素
find_end 				在区间中查找另一个区间最后一次出现的位置(可自定义比较器)
find_first_of 			在区间中查找第一个出现在另一个区间中的元素 (可自定义比较器)
adjacent_find 在		区间中寻找第一次出现连续两个相等元素的位置(可自定义比较器)
search 					在区间中查找另一个区间第一次出现的位置(可自定义比较器)
search_n 				在区间中查找第一次出现等于某值的连续n个元素(可自定义比较器)
equal 					判断两区间是否相等(可自定义比较器)
mismatch 				逐个比较两个区间的元素,返回第一次发生不相等的两个元素的位置(可自定义比较器)
lexicographical_compare 按字典序比较两个区间的大小(可自定义比较器)

min_element和max_element的实例
重载小于号运算符后,取数组中的最大和最小值

#include <iostream
>
#include <algorithm>
using namespace std
;
class A {
public:
int n;
A(int i):n(i) { }
};
bool operator<( const A & a1, const A & a2) {
cout << “< called” << endl
;
if( a1.n == 3 && a2.n == 7 )
return true;
return false;
}
int main() {
A aa[] = { 3,5,7,2,1 };
cout << min_element(aa,aa+5)->n << endl;
cout << max_element(aa,aa+5)->n << endl;
return 0;
}
/*
输出:
< called
< called
< called
< called
3
< called
< called
< called
< called
7
*/

2.变值算法

此类算法会修改源区间或目标区间元素的值,值被修改的那个区间, 不可以是属于关联容器的

for_each 				对区间中的每个元素都做某种操作
copy 					复制一个区间到别处
copy_backward 			复制一个区间到别处, 但目标区前是从后往前被修改的
transform 				将一个区间的元素变形后拷贝到另一个区间
swap_ranges 			交换两个区间内容
fill 					用某个值填充区间
fill_n 					用某个值替换区间中的n个元素
generate			    用某个操作的结果填充区间
generate_n 				用某个操作的结果替换区间中的n个元素
replace 				将区间中的某个值替换为另一个值
replace_if 				将区间中符合某种条件的值替换成另一个值
replace_copy			将一个区间拷贝到另一个区间,拷贝时某个值要换成新值拷过去
replace_copy_if 		将一个区间拷贝到另一个区间,拷贝时符合某条件的值要换成新值拷过去

transform函数模板

transform
template<class InIt, class OutIt, class Unop>
OutIt transform(InIt first, InIt last, OutIt x, Unop uop);
对[first,last)中的每个迭代器I,
• 执行 uop( * I ); 并将结果依次放入从 x 开始的地方
• 要求 uop( * I ) 不得改变 * I 的值
本模板返回值是个迭代器, 即 x + (last-first)
• x可以和 first相等

变值算法实例

#include <vector>
#include <iostream>
#include <numeric>
#include <list>
#include <algorithm>
#include <iterator>
using namespace std;
class CLessThen9 {
public:
bool operator()( int n) { return n < 9; }
};
void outputSquare(int value ) { cout << value * value << " "; }
int calculateCube(int value) { return value * value * value; }
int main() {
const int SIZE = 10;
int a1[] = { 1,2,3,4,5,6,7,8,9,10 };
int a2[] = { 100,2,8,1,50,3,8,9,10,2 };
vector<int> v(a1,a1+SIZE);
ostream_iterator<int> output(cout," ");
random_shuffle(v.begin(),v.end());
cout << endl << "1) ";
copy( v.begin(),v.end(),output);
copy( a2,a2+SIZE,v.begin());
cout << endl << "2)";
cout << count(v.begin(),v.end(),8);
cout << endl << "3)";
/*
输出:
1) 5 4 1 3 7 8 9 10 6 2
2) 2
3) 6
//1) 是随机的
*/
cout << count_if(v.begin(),v.end(),CLessThen9());
cout << endl << "4) ";
cout << * (min_element(v.begin(), v.end()));
cout << endl << "5) ";
cout << * (max_element(v.begin(), v.end()));
cout << endl << "6) ";
cout << accumulate(v.begin(), v.end(), 0); 
/*
输出:
4) 1
5) 100
6) 193
*/

copy 函数模板(算法)

template<class InIt, class OutIt>
OutIt copy(InIt first, InIt last, OutIt x);
本函数对每个在区间[0, last - first)中的N执行一次
*(x+N) = *(first + N), 返回 x + N
对于copy(v.begin(),v.end(),output);
first 和 last 的类型是 vector<int>::const_iterator
output 的类型是 ostream_iterator<int> 
template<class _II, class _OI>
inline _OI copy(_II _F, _II _L, _OI _X)
{
for (; _F != _L; ++_X, ++_F)
*_X = *_F;
return (_X);
}

第三类删除算法

删除一个容器里的某些元素
删除 – 不会使容器里的元素减少
• 将所有应该被删除的元素看做空位子
• 用留下的元素从后往前移, 依次去填空位子
• 元素往前移后, 它原来的位置也就算是空位子
• 也应由后面的留下的元素来填上
• 最后, 没有被填上的空位子, 维持其原来的值不变
删除算法不应作用于关联容器

删除算法成员

remove 						删除区间中等于某个值的元素
remove_if 					删除区间中满足某种条件的元素
remove_copy					拷贝区间到另一个区间. 等于某个值的元素不拷贝
remove_copy_if 				拷贝区间到另一个区间. 符合某种条件的元素不拷贝
unique 						删除区间中连续相等的元素, 只留下一个(可自定义比较器)
unique_copy					拷贝区间到另一个区间. 连续相等的元素, 只拷贝第一个到目标区间 (可自定义比较器)

uniqe函数模板:

unique
template<class FwdIt>
FwdIt unique(FwdIt first, FwdIt last);
用 == 比较是否等
template<class FwdIt, class Pred>
FwdIt unique(FwdIt first, FwdIt last, Pred pr);
用 pr (x,y)为 true说明x和y相等
对[first,last) 这个序列中连续相等的元素, 只留下第一个
返回值是迭代器, 指向元素删除后的区间的最后一个元
素的后面

删除算法实例:注意观察并不是真正删除这个元素。

int main(){
int a[5] = { 1,2,3,2,5 };
int b[6] = { 1,2,3,2,5,6 };
ostream_iterator<int> oit(cout,",");
int * p = remove(a,a+5,2);
cout << "1) "; copy(a,a+5,oit); cout << endl; //输出 1) 1,3,5,2,5,
cout << "2) " << p - a << endl; //输出 2) 3
vector<int> v(b,b+6);
remove(v.begin(), v.end(),2);
cout << "3) "; copy(v.begin(), v.end(), oit); cout << endl;
//输出 3) 1,3,5,6,5,6,
cout << "4) "; cout << v.size() << endl;
//v中的元素没有减少,输出 4) 6
return 0;
}

第四类变序算法

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

常用的变序算法
stable_patition
把区间内满足某个条件的元素移到前面,不满足该条件的移到后面
而对这两部分元素, 分别保持它们原来的先后次序不变
random_shuffle
template
void random_shuffle(RanIt first, RanIt last);
随机打乱[first,last) 中的元素, 适用于能随机访问的容器‘
reverse
template
void reverse(BidIt first, BidIt last);
颠倒区间[first,last)顺序
next_permutation
template
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;
}
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;}输出:
/*
132
213
231
312
321
*/

排序算法

  • 比前面的变序算法复杂度更高, 一般是O(nlog(n))
  • 排序算法需要随机访问迭代器的支持
  • 不适用于关联容器和list
    排序算法举例
sort 					将区间从小到大排序(可自定义比较器)
stable_sort 			将区间从小到大排序并保持相等元素间的相对次序(可自定义比较器)
partial_sort 			对区间部分排序, 直到最小的n个元素就位(可自定义比较器)
partial_sort_copy 		将区间前n个元素的排序结果拷贝到别处源区间不变(可自定义比较器)
nth_element 			对区间部分排序, 使得第n小的元素(n从0开始算)就位, 而且比它小的都在它前面, 比它大的都在它后面(可自定义比较器)
make_heap 				使区间成为一个“堆”(可自定义比较器)
push_heap 				将元素加入一个是“堆”区间(可自定义比较器)
pop_heap 				从“堆”区间删除堆顶元素(可自定义比较器)
sort_heap 				将一个“堆”区间进行排序,排序结束后,该区间就是普通的有序区间,不再是 “堆”了(可自定义比较器)
sort 快速排序
template<class RanIt>
void sort(RanIt first, RanIt last);
按升序排序
判断x是否应比y靠前, 就看 x < y 是否为true
template<class RanIt, class Pred>
void sort(RanIt first, RanIt last, Pred pr);
按升序排序
判断x是否应比y靠前, 就看 pr(x,y) 是否为true

排序算法实例

#include <iostream>
#include <algorithm>
using namespace std;
class MyLess {
public:
bool operator()( int n1,int n2) {
return (n1 % 10) < ( n2 % 10);
}
};
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] << " ";
}
/*
按个位数大小排序,
按降序排序
输出:
111 2 14 78 9
111 78 14 9 2
*/

有序区间算法:

  • 要求所操作的区间是已经从小到大排好序的
  • 需要随机访问迭代器的支持
  • 有序区间算法不能用于关联容器和list
    算法举例
binary_search				判断区间中是否包含某个元素
includes 					判断是否一个区间中的每个元素,都在另一个区间中
lower_bound 				查找最后一个不小于某值的元素的位置
upper_bound 				查找第一个大于某值的元素的位置
equal_range 				同时获取lower_bound和upper_bound
merge 						合并两个有序区间到第三个区间
set_union 					将两个有序区间的并拷贝到第三个区间
set_intersection 			将两个有序区间的交拷贝到第三个区间
set_difference 				将两个有序区间的差拷贝到第三个区间
set_symmetric_difference 	将两个有序区间的对称差拷贝到第三个区间
inplace_merge 				将两个连续的有序区间原地合并为一个有序区间
binary_search
折半查找
要求容器已经有序且支持随机访问迭代器, 返回是否找到
template<class FwdIt, class T>
bool binary_search(FwdIt first, FwdIt last, const T& val);
上面这个版本, 比较两个元素x, y 大小时, 看 x < y
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, uper_bound, equal_range
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 小
··································分隔符·······································
upper_bound
template<class FwdIt, class T>
FwdIt upper_bound(FwdIt first, FwdIt last, const T& val);
要求[first,last)是有序的
查找[first,last)中的, 最小的位置 FwdIt, 使得[FwdIt,last)
中所有的元素都比 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的结果
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值