SGISTL源码探究-STL中的算法(前言)

前言

我们目前已经分析了STL中的六大组件的一半。剩下的还有算法、仿函数、配接器,已经分析了配置器、迭代器、容器部分。

接下来进入到剩下的三大组件中最复杂的算法部分,关于STL中的算法,它实现了很多功能,但是分析这部分的时候我只打算选择一部分比较经典的算法进行分析(因为这部分的算法实在是太多了),只要掌握了分析的方法,以后自己遇到其他的STL算法或者感兴趣的,直接阅读源码就行了。

概览

大致分类

STL中的算法大致分为质变与非质变算法。
质变是指会改变操作对象的内容,比如sortswapfill等算法,但是也可以选择不在原操作对象上进行操作,可以选择在一个复制的操作对象上进行,然后返回;
非质变算法则不会改变操作对象的内容,比如findsearchmax等算法。

泛化

STL中,关于泛化的思想很值得学习,比如之前在分析容器时,我们发现一个容器可以接受基本上所有的类型作为存储的元素,而且其内部提供的操作通过迭代器也可以完成,这就是泛化的体现。
我们可以通过迭代器对指向的容器调用STL中提供的泛型算法。这样不管是什么数据类型,我们都可以通过容器存储,然后使用迭代器将其与算法联系起来,从而进行任何合理的操作。这就是泛化的魅力。
在《STL源码剖析》中的原话是:只要把操作对象的型别加以抽象化,把操作对象的标示法和区间目标的移动行为抽象化,整个算法也就在一个抽象层面上工作了。整个过程称为算法的泛型化,简称泛化。这些的实现,都是建立在模板机制的基础上,从而实现了高度的抽象。下面举两个体现算法的泛化的例子。

  • 在平时使用STL中提供的算法时,可以发现前两个参数都是传入的迭代器的范围[first, last),这也是为了泛化。例如针对数组,我们可以通过[array, array + n)这样来实现一个范围的选取,但是如果针对链表,我们就无法通过这种方式来表达链表的头和尾了,因此迭代器的作用就来了,传入[first, last),而first如何遍历到last这件事,就不需要算法关心了,在迭代器的实现中自有办法。
  • 不难发现传入的迭代器范围都是前闭后开区间,它的作用就是用last来表示防止越界。比如一个大小为n的数组,当我们访问第n号元素时,其实是越界了,这个时候last是指向第n号元素的,我们可以对比当前的迭代器和last是否相等来判断是否数组已经到达末尾。还有比如链表,链表的最后一个节点的下一个节点是NULL,但是我们不能直接使用ptr == NULL这种方法来判断是否到达链表末尾,因为这样就破坏了泛型的思想,从而使用一个辅助节点,让last指向该辅助节点即可(list的实现就是采用这种方法)。

根据实际的情况不同,同一个算法采取的方法可能并不同。比如copy算法,如果指向是基础的数据类型,那么直接调用像memmove这类函数就行了,但是如果是对象,可能就还要涉及到调用拷贝构造函数等方面的了,比如sort算法,STL中采用的并不止快速排序这一种排序方法,而是有多种排序算法,根据情况不同,调用的最合适的排序算法。

总之,根据迭代器提供的信息(比如它的类型),选择效率最高的操作,这便是STL中某种具体的算法做的事。此刻你应该可以了解到迭代器的重要性了,它之所以会提供那五种相应型别,并不是没有作用的,而且它连接了容器与算法。

其他

关于数值的算法,比如accumulatepower、这些算法,都在stl_numeric.h中。
关于常用的算法,比如fillcopymaxmin等算法,在stl_algobase.h中。
而其他的算法,在stl_algo.h中。

SGISTL的实现中,有部分是不属于STL标准规格中的算法,分析的时候会指出。

小结

本小节我们只对STL中的算法实现的思想以及一些概念进行了讲解,没有涉及到具体的算法,但是泛化的思想一定要有所理解,不然看这一部分就仅仅是学习复习算法知识了。
在下一小节我们将正式进入到源码分析部分。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值