【STL】算法(algorithms)

再好的编程技巧,也无法让一个笨拙的算法起死回生。选择了错误的算法,便注定了失败的命运。 - 侯捷

概述

算法,问题之解法也。

从某些意义上来说,写的每个程序都是一种算法,每个函数都是用来解决某个问题的。我们常见的排序、查找等算法,都被收录于STL之中。同时,为了提高某些算法的性能,还存在一些相匹配的数据结构。比如:二叉树、红黑树等都是为了提高查找效率。堆、最大优先队列等为了提高排序效率。

算法复杂度的计算比较复杂繁琐,具体可以参考《算法导论》第三章函数的增长。

在这里,我给大家一个自己使用的简单判别技巧(仅是个人见解),一次for循环就是O(n),如果嵌套一次就乘n。如果有对整个数组有折半,就是O(logn)。

所有的STL算法都作用于迭代器所在区间上,分为质变和非质变。所谓质变即可以更改元素内容,如:拷贝、互换、替换、删除等,非质变即不能更改元素内容,如:查找、匹配、计数等。

所有泛型算法的前两个参数一般为一对迭代器,即first和last,C++习惯于左闭右开。有些算法不只支持一个版本,还可以接受外界的仿函数,方便采取其他策略。质变算法一般分为两个版本,一个是in-place(就地解决),另一个是copy(另地解决)。

算法的泛化过程

将一个算法转化成程序代码,解决一个问题是最愉快的工作。但是更改一段代码适配其他容器or场景工作,应该是每个程序员最头疼的事情。将算法独立于数据结构之外,让算法具有复用性,就显得尤为重要。

这就要提到STL的厉害之处,在容器和算法中间,利用迭代器作为桥梁,实现了这种泛化。

例如,find函数,利用迭代器即可写出:

template<class Iterator,class T>
Iterator find(Iterator begin,Iterator end,const T& value){
	while(begin!=end && *begin!=value){
		++begin;
	}
	return begin;
}

算法举例

accumulate

算法accumulate用来计算init和[first,last)内所有元素的总和。提供一个初始值init是为了当[first,last)为空时,仍可以返回一个明确定义的值。
版本1:

template<class InputIterator,class T>
T accumulate(InputIterator first,InputIterator last,T init){
	for( ; first!=last;++first)
		init=init+*first;
	return init;
}

版本2:

template<class InputIterator,class Tclass BinaryOperation>
T accumulate(InputIterator first,InputIterator last,T init,BinaryOperation binary_op){
	for( ; first!=last;++first)
		init=binary_op(init,*first);   //对元素进行二元操作
	return init;
}

这里的二元操作符并不需要满足交换律和结合律,因为accumulate的行为顺序有明确定义。

swap

该函数用来交换(对调)两个对象的内容。

template<class T>
inline void swap(T&a,T&b){
	T tmp=a;
	a=b;
	b=tmp;
}

STL中算法众多,为了提高效率,用来各种办法,包括函数重载、性别特性、偏特化等编程技巧。比较复杂,就不一一介绍。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值