一、算法概观

以有限的步骤,解决逻辑或数学上的问题,这一专门科目我们称为算法。特定的算法往往搭配特定的数据结构,例如binary search tree(二叉搜索树)和 RB-tree 便是为了解决查找问题而发展出来的特殊数据结构。几乎可以说,特定的数据结构是为了实现某种特定的算法。本章所讨论的,是可施行于“无太多特殊条件限制”之空间中的某一段元素区间的算法。

1. 算法分析与复杂度表示O()

参见算法与数据结构相关书籍,如《算法设计与分析》《数据结构》等。

2. STL 算法总览

      

3. 质变算法mutating algorithms——会改变操作对象之值

所有的STL算法都作用在由迭代器[first, last) 所标示出来的区间上。所谓“质变算法”,是指运算过程中会更改区间内(迭代器所指)的元素内容。诸如拷贝(copy)、互换(swap)、替换(replace)、填写(fill)、删除(remove)、排列组合(permutation)、分割(partition)、随机重排(random shuffling)、排序(sort)等算法,都属此类。

4. 非质变算法nonmutating algorithms——不改变操作对象之值

所有的STL算法都作用在  由迭代器[first, last) 所标示出来的区间上。所谓“非质变算法”,是指运算过程中不会更改区间内(迭代器所指)的元素内容。诸如查找(find)、匹配(search)、计数(count)、巡访(for_each)、比较(equal,mismatch)、寻找极值(max,min)等算法,都属此类。

5. STL算法的一般形式

所有泛型算法的前两个参数都是一对迭代器,通常由first和last形成一个“前闭后开”区间[first, last)。根据行进特性,迭代器可分为5类,每一个STL算法的声明,都表现出它所需要的最低程度的迭代器类型。例如find() 需要一个InputIterator,这是它的最低要求,但它也可以接受更高类型的迭代器,如ForwardIterator,BidirectionalIterator或RandomAccessIterator,在 STL——迭代器与traits编程技法 文章中阐述的,不论ForwardIterator或BidirectionalIterator或RandomAccessIterator也都是一种InputIterator。但如果你交给find() 一个OutputIterator,会导致错误。

将无效的迭代器传给某个算法,虽然是一种错误,却不保证能够在编译时期就被捕捉出来,因为所谓“迭代器类型”并不是真实的型别,它们只是function template的一种型别参数(type parameters)。

许多STL算法不只支持一个版本。这一类算法的某个版本采用缺省运算行为,另一个版本提供额外参数,接受外界传入一个仿函数(functor),以便采用其他策略。

质变算法通常提供两个版本:一个是in-place(就地进行)版,就地改变其操作对象;另一个是copy(另地进行)版,将操作对象的内容复制一份副本,然后在副本上进行修改并返回该副本。copy版本总是以_copy作为函数名称后缀,如replace()和replace_copy()。并不是所有质变算法都有copy版,例如sort()就没有。如果我们希望以这类“无copy版本”之质变算法施行于某一段区间元素的副本身上,我们必须自行制作并传递那一份副本。

所有的数值(numeric)算法都实现于SGI<stl_numeric.h>之中,这是个内部文件,STL 规定用户必须包含的是上层<numeric>。其他STL算法都实现于SGI 的<stl_algo.h> 和 <stl_algobase.h>文件中,也都是内部文件;欲使用这些算法,必须先包含上层相关头文件<algorithm>。

二、算法的泛化过程 : "操作对象的型别+操作对象的标示法+区间目标的移动行为"三者的抽象化

如何将算法独立于其所处理的数据结构之外,关键在于,只要把操作对象的型别(使用模板template)加以抽象化,把操作对象的标示法(使用容器对应的迭代器来标示操作对象)和区间目标的移动行为(例如,一套STL容器的设计标准就规定要设计一个符合STL抽象算法操作行为的容器需要满足的条件,只有定义好了容器的设计标准,才有可能对“各种容器的不同操作行为”进行统一(也即抽象出)形成一个抽象行为,使得这个抽象行为在不同容器之上都能正常工作。而迭代器在这里便充当了容器和算法之间的胶着剂——通过迭代器(迭代器算法)取得容器中的对象,交予算法进行处理。)抽象化,整个算法也就在一个抽象层面上工作了。整个过程称为算法的泛型化,简称泛化。

三、算法实例

在《STL源码剖析》6.3节中,有针对各种算法,包括数值算法,基本算法,set相关算法,heap算法,以及其他多种常用算法的运用实例,详见书籍。

这里重点提一下下面几类算法:

(1)copy算法——强化效率无所不用其极

不论是对客户程序或是STL内部而言,copy()都是一个常常被调用的函数。由于copy进行的是复制操作,而复制操作不外乎运用assignment operator或copy constructor(copy算法用的是前者),但是某些元素型别拥有的是trivial(无价值的,微不足道的) assignment operator,因此,如果能够使用内存直接复制行为(例如C标准函数memove或memcpy),便能够节省大量时间。为此,SGI STL的copy算法用尽各种办法,包括函数重载、型别特性、偏特化等编程技巧,无所不用其极地加强效率。

注意,copy算法,需要特别注意区间重叠的情况:  

  如图6-3所示:

  如果输入区间和输出区间完全没有重叠,当然毫无问题,否则便需特别注意.为什么图6-3第二种情况(可能)会产生错误?从源代码可得知,copy算法是一一进行元素的赋值操作,如果输出区间的起点位于输入区间内,copy算法便(可能)会在输入区间的(某些)元素尚未被复制之前,就覆盖其值,导致错误哦结果.在这里我一再使用"可能"这个字眼,是因为,如果copy算法根据其所接收的迭代器的特性决定调用memmove()来执行任务,就不会造成上述错误,因为memmove()会先将整个输入区间的内容复制下来,没有被覆盖的危险.

(2)sort算法

STL所提供的各式各样算法中,sort()是最复杂最庞大的一个。这个算法接受两个RandomAccessIterators(随机存取迭代器),然后将区间内的所有元素以渐增方式由小到大重新排列。第二个版本则允许用户指定一个仿函数,作为排序标准。STL的所有关系型容器都拥有自动排序功能(底层结构采用RB-tree),所以不需要用到这个sort算法。至于序列式容器中的stack、queue和priority-queue都有特别的出入口,不允许用户对元素排序。剩下vector、deque和list,前两者的迭代器属于RandomAccessIterator,适合使用sort算法,list的迭代器则属于BidirectionalIterators,不在STL标准之列的slist,其迭代器更属于RorwardIterator,都不适合使用sort算法。

STL 的sort算法,数据量大时采用Quick Sort,分段递归排序。一旦分段后的数据量小于某个门槛,为避免Quick Sort的递归调用带来过大的额外负荷,就改用Insertion Sort。如果递归层次过深,还会改用Heap Sort。 关于Quick Sort和Insertion Sort算法,以及排序相关的其他算法,参考相关算法书籍。

STL——算法简介的更多相关文章

  1. C++11 STL算法简介

    STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库.它被容纳于C++标准程序库(C++ Standard Library)中,是ANS ...

  2. STL所有算法简介 (转) http://www.cnblogs.com/yuehui/archive/2012/06/19/2554300.html

    STL所有算法简介 STL中的所有算法(70个) 参考自:http://www.cppblog.com/mzty/archive/2007/03/14/19819.htmlhttp://hi.baid ...

  3. STL的简介

    Standard Template Library,(标准模板库)<来自百度百科的整理> ————可复用性(reusability) STL是基于模板,内联函数的使用使得生成的代码短小高效 ...

  4. webrtc 的回声抵消(aec、aecm)算法简介(转)

    webrtc 的回声抵消(aec.aecm)算法简介        webrtc 的回声抵消(aec.aecm)算法主要包括以下几个重要模块:1.回声时延估计 2.NLMS(归一化最小均方自适应算法) ...

  5. STL算法

    STL算法部分主要由头文 件<algorithm>,<numeric>,<functional>组成.要使用 STL中的算法函数必须包含头文件<algorit ...

  6. 【STL源码学习】STL算法学习之四

    排序算法是STL算法中相当常用的一个类别,包括部分排序和全部排序算法,依据效率和应用场景进行选择. 明细: sort 函数原型: template <class RandomAccessIter ...

  7. 【STL源码学习】STL算法学习之三

    第一章:前言 数量不多,用到的时候会很爽. 第二章:明细 STL算法中的又一个分类:分割:将已有元素按照既定规则分割成两部分.  is_partitioned 函数原型: template <c ...

  8. 【STL源码学习】STL算法学习之二

    第一章:前言 学习笔记,记录学习STL算法的一些个人所得,在以后想用的时候可以快速拾起. 第二章:明细 copy 函数原型: template <class InputIterator, cla ...

  9. 【转】三十分钟学会STL算法

    转载自: http://net.pku.edu.cn/~yhf/UsingSTL.htm 这是本小人书.原名是<using stl>,不知道是谁写的.不过我倒觉得很有趣,所以化了两个晚上把 ...

随机推荐

  1. I2C上拉电阻

    在一些PCB的layout中,大家往往会看到在I2C通信的接口处,往往会接入一个4.7K的电阻,有的datasheet上面明确有要求,需要接入,有的则没有要求.   I2C接口 对于单片机来讲,有些I ...

  2. 【转载】Exchange 2010配置与安装实用手册

    Exchange 2010配置与安装实用手册 在Exchange 2010配置的时候主要分三大部分,这分别是网络配置.准备存储以及相关的安装策略和过程.同时还需要注意和其他的Windows软件相协调. ...

  3. Oracle数据库的语句级读一致性

    数据库:Oracle 前提:假定100万行的记录,在最后一行有一个数据a=1. 实验:你在9:00的时候查找数据,9:05的时候查到最后一行:但是,在9:01的时候有人修改了最后一行数据并提交(com ...

  4. SpringMVC系列(七)视图解析器和视图

    在springmvc.xml里面配置视图解析器 <!-- 配置视图解析器: 如何把 handler 方法返回值解析为实际的物理视图 --> <bean class="org ...

  5. 一个简单的perl程序

    和朋友聊天,说perl的神奇,最主要的是一行代码搞定所有. 想想用python3写的测试脚本,觉得还是有点多的,真的用几行代码写一个测试脚本,可以节约不少时间. 当然,网上黑perl的还是很多,不过自 ...

  6. CI框架 -- URL

    移除 URL 中的 index.php 默认情况,你的 URL 中会包含 index.php 文件: example.com/index.php/news/article/my_article 如果你 ...

  7. Oracle数据库order by排序查询分页比不分页还慢问题解决办法

    简单说下问题,有一个JDBC的查询SQL,分页查询语句中有一个排序order by create_time,理论上来说JDBC查询已经是比较底层的技术了,没有像Hibernate.MyBatis那样又 ...

  8. js 历史

    原文http://javascript.ruanyifeng.com/introduction/history.html JavaScript的诞生 JavaScript 因为互联网而生,紧随着浏览器 ...

  9. Allure Report使用

    https://blog.csdn.net/liuchunming033/article/details/79624474#commentBox https://blog.csdn.net/lihua ...

  10. centos6.5 手动安装gcc

    gcc版本:gcc-4.4.7 rpm -Uvh  mpfr-2.4.1-6.el6.x86_64.rpm rpm -Uvh  cpp-4.4.7-16.el6.x86_64.rpmrpm -Uvh  ...