6 算法_第四版

通过提升速度来解决其他方式无法解决的问题,是研究算法的设计和性能的主要原因之一。结合python代码看,容易理解。
研究新问题时,最好的方法是先实现一个能想到的最简单程序,当它成为瓶颈时再继续改进它。

1 排序

考虑:比较次数、交换次数;
排序的主要原因:在有序的数组中查找一个元素比在无序的数组中查找简单的多。通用排序算法是最重要的。
电话黄页按姓氏排序;歌曲按作家名或歌曲名排序;搜索引擎按搜索结果的重要性排序;矩阵工具按对称矩阵的真实特征值排序。只要数组是有序的,很多其他任务也更容易完成。

1)选择排序

不断地选择剩余元素之中的最小者

2)插入排序

保持当前索引左边的所有元素都是有序的,适用于部分有序的数组

改进:在内循环中将较大的元素都向右移动,而不总是交换两个元素?

3)希尔排序

基于插入排序,使数组中任意间隔为h的元素都是有序的

shell sort,权衡了子数组的规模和有序性;子数组部分有序的程度取决于递增序列的选择,透彻理解希尔排序的性能至今仍是挑战。对于给定的递增序列,运行时间达不到平方级别,比插入和选择排序要快的多,并且数组越大优势越大。

4)归并排序

以索引来切分,递归地将数组分成两半来排序,然后将结果归并起来;缺点是所需的额外空间和数组长度成正比

归并排序是一种渐进最优的基于比较排序的算法。持续改进:小规模子数组切换到插入排序;测试数组是否已经有序;不将元素复制到辅助数组。
由顶向下实现:1.分成两边,挨个遍历、比较,放入辅助数组;2.有一边已经遍历完,那么剩下的都放入辅助数组。

5)快速排序

以数组内容来切分,将数组分成两部分,将两部分独立排序,递归地调用;优点是原地排序,对归并排序的补充

优势:内循环简洁,将数组元素与定值比较;比较次数少,平均而言切分元素都能落在数组的中间。持续改进:小规模子数组切换到插入排序;三取样切分;熵最优的排序,比如包含大量重复元素。
二叉排序树:其左子树小于根结点的值,右子树大于根结点的值,思路就是特殊的快速排序;中序遍历,左子树、根结点、右子树;前序遍历,根结点、左子树、右子树;后序遍历,左子树、右子树、根结点。
排序递归、遍历递归!不管怎样都是从根节点开始!

6)堆排序

两个阶段:1.构造堆,线性时间;2.在下沉排序阶段,迭代地“删除最小元素”,得到排序结果

优先队列、最大堆:其子结点全都小于根结点
对数组进行原地排序,不需要额外空间。

2 查找

存储键值对,支持两种操作:查找get和插入put;需要实现高效的符号表(字典)。
提供接口:void put/Value get/void delete/boolean contains/boolean isEmpty/int size/Iterable keys
除了顺序查找外,都是先按某种方法排序,再使用相应的规则查找。最常见:二分查找。

1)二叉查找树

最大/小键max/min;向上/下取整ceiling/floor;数量size;查找select;排名rank;删除delete(最难)/遍历keys
在二叉查找树中,所有操作在最坏情况下所需的时间都和树的高度成正比;
随机键构造的二叉查找树的平均高度为lgN;基于二叉查找树的符号表。

2)红黑树

2-3查找树:一个结点保存多个键;查找和插入访问的结点必然不超过lgN个。
红黑树(平衡二叉查找树):红链接将两个2-结点连起来构成一个3-结点,黑链接是2-3树中的普通链接。

3)散列表

用算术操作将键转化为数组的索引,来访问数组中的键值对。在时间和空间上找到了权衡,不限制内存的话,直接将键作为数组的索引;不限制时间的话,使用无序数组进行顺序查找;而且不必重写代码,调整散列算法的参数就可以在时间和空间上做出取舍。
散列函数:将被查找的键转化为数组的索引。最好满足三个条件:一致性,等价的键产生相等的值;高效性,计算简便;均匀性,均匀地散列所有键。
处理碰撞冲突:当两个或多个键都散列到相同索引值的情况。拉链法,使用链表的每个结点存储散列值为该元素的索引的键值对,首先根据散列值找到对应的链表,然后沿着链表顺序查找对应的键。

3 图

图算法Graph:沿着连接能否从一个结点到另一个结点?有多少结点和指定的结点相连?两个结点间最短的连接是哪一条?
广泛应用:1)地图,最短路径;2)网页信息,页面、超链接、搜索引擎;3)任务调度,任务、限制条件;4)商业交易,客户、交易;5)社交,人、朋友关系;6)软件,类和模块、调用关系

1)无向图

路径,u-v-w-x;环,u-v-w-x-u
查找顶点Search(Graph G, int s):boolean marked(int v)/int count()
查找路径Paths(Graph G, int s):boolean hasPathTo(int v)/Iterable pathTo(int v)
连通分量CC(Graph G):boolean connected(int v, int w)/int count()/int id(int v)
深度优先搜索:递归遍历所有顶点;将顶点标记为“已访问”,然后访问它的所有未被标记过的邻接点;结果是数组,所需的时间和路径的长度成正比。
广度优先搜索:找出单点最短路径,显式地使用队列,以保存所有已经被标记过,但其邻接表还未被检查过的顶点;将顶点标记为“已访问”,然后将它的所有未被标记过的邻接点加入队列;结果是数组,表示s到每个与s连通的顶点的最短路径,所需的时间在最坏情况下和V+E成正比。

2)有向图

3)加权图

4)加权有向图

4 字符串

1)字符串排序

2)单词查找树

3)子字符串查找

4)正则表达式

5)数据压缩

你可能感兴趣的:(6 算法_第四版)