C++ STL和泛型编程(三)---部分算法源码剖析(Algorithms)

一、结构形式

template<typename Iterator>
std::Algorithm(Iterator itr1, Iterator itr2, ...){
	...
}

算法的形式为模板函数:
且其第一、第二传入模板参数均为迭代器,
额外函数模板参数一般系统默认的【主版本的算法,默认的算法实现操作】;
额外函数模板参数有自己定义的函数或函数对象【此版本的算法,即自行定义算法的实现操作】。

二、算法accumulate

在这里插入图片描述
由图知,左上为主版本算法,左下为次版本算法即多了个函数模板参数【可传入自定义操作函数或函数对象】。
右边中,传入的myfunc便是一个函数参数,而myobj便是个函数对象参数【一般是个函数类,其内部只进行operator()的操作】,所以传入这两个函数参数和函数类对象参数的accumulate()算法调用的是左下角的次版本。

三、算法for_each

在这里插入图片描述
与上类似。

四、算法replace, replace_if, replace_copy

在这里插入图片描述
由上知这些模板函数都暗示了应传入对应的iterator_category。
其中对于replace_if,一般带if的都是要传入对于的操作函数或函数对象来告诉对应if的操作条件,这里便暗示需传入Predicate类型【应为一个可以返回真或假的判断式类型】 的pred()函数来表示if的操作条件的需求。

五、算法count, count_if

在这里插入图片描述
这里的count_if中也需传入一个函数或函数对象来表示if操作条件的情况。

六、find, find_if

在这里插入图片描述
注意:associated containers & unordered containers内部为rb_treehashtable结构,所以用自己内部重写的成员函数find()查找元素更快!

七、算法sort

在这里插入图片描述这里应注意:

1.associated containers 和 unordered containers内部都是已经经过一定的排序规则而放置的,所以其不带成员函数sort(),也不应该对它们调用 ::sort() 函数。

2.另外 ::sort() 函数要求的iterator是random_iterator_tag类型的,而list 和 forward_list的iteratorbidirectional_iterator_tag或forward_iterator_tag类型的,并不匹配,所以list 和 forward_list需要内部重写自己的成员函数sort()。

八、算法binary_search

在这里插入图片描述注意:算法binary_search要求是在已sorted=的基础上才可以使用的!

由binary_search的源码知,其传入的迭代器类型应为forward_iterator_tag类型,而且其内部实际调用的是lower_bound()函数。


由右边的lower_bound()函数的源码知:

1.先由萃取机取出对应iterator_category的difference_type类型,并声明对应difference_type类型的变量count, step;
2.将其实指针赋值给迭代器it,然后step=count/2即所需移动步骤划分为一半,调用advance()将it移动step步,此时it指针已跑到中间位置;
3.
(1)若此时中间位置的元素(*it)小于目标元素val,则取后半段进行下一轮的比较,此时it指针先跳到后半段的下一个元素即first = ++it,同时所取的后半段大小为cout -= step + 1;
(2)若此时中间位置的元素(*it)不小于目标元素val,则取前半段即it指针位置不变,然后前半段大小为count = step;
4.重新执行2,3步骤,直到cout的大小为0则可得出对应的已排序的序列中,不小于val的第一个位置,并返回【此便是二分查找法】。

同理,upper_bound()函数便是返回已排序的序列中,不小于val的最后一个位置。


在调用完lower_bound()函数后,便得到一个指针返回值:
first == lastval > 最末的元素,即此时经过lower_bound()函数后,it已经移动到last的位置,则返回值first==last】 或者 val < *first或者一开始val就是小于首元素的,则此时first指针经过lower_bound()函数后,并未发生移动,即仍是指向首元素的】,则binary_search()返回0即查找失败不存在这样的插入位置。

(算法源码进一步优化:
在binary_search的源码中,可以先判断 !(val < *first)!(val > (*last - 1)) ,这样证明val比整个序列的元素都小或者比整个序列元素都大,则无进入后续操作的必要了!!)

九、关于reverse iterator, rbegin(), rend()

在这里插入图片描述注意:
1.end()是指向最末元素的下一个位置(已是容器外的位置了)。
2.实现rbegin(),rend()函数操作的都是通过iterator adapter去操作的。
3.reverse iterator的指向是逆过来反向指向的了,其++操作也是逆序反向操作的!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值