《算法4》读书笔记(二)

第二章——排序算法

1.选择排序:首先找到数组中最小的元素,将它和数组的第一个元素交换位置,然后在剩下的元素中找到最小的元素,将其和数组的第二个元素交换位置。。。直到将整个数组排序。其运行时间和输入无关,一个有序的数组或主键全部相等的数组和元素随机排列的数组相比,所用的排序时间一样。

在这里插入图片描述

2.与选择排序一样,当前索引左边的所有元素都是有序的,但其最终位置还不确定,为了给更小的元素腾出空间,它们可能会移动,但当索引到达数组的最右边时,数组排序就完成了。和选择排序不同,插入排序所用的时间取决于输入元素的初始顺序。(将a[i]插入到a[i-1],a[i-2],a[i-3]…a[0]中)

在这里插入图片描述
在这里插入图片描述

插入排序对部分有序的数组有效,也适合小规模数组。

3.在排序的过程中,插入排序不会访问当前索引右边的元素,选择排序不会访问当前索引左边的元素。一般来说插入排序比选择排序快一倍(或者是其他常数),两者的运行时间都是平方级别的。

4.希尔排序的思想是使数组中任意间隔为h的元素都是有序的(j-i=h),这样的数组被称为h有序数组。h个有序子数组:[L,M,P,T],[E,H,S,S],[E,L,O,X],[A,E,L,R]。

在这里插入图片描述

在这里插入图片描述

插入排序是h为1的时特殊的希尔排序。和选择、插入排序相比,希尔排序可以用于大型(任意排序,不一定是随即的)数组排序。希尔排序的运行时间达不到平方级别,在最坏情况下以上代码的比较次数和N^(3/2)成正比。

5.归并排序的优点是其将任意长度的数组排序所需时间和N*logN成正比,缺点是它所需的额外空间和N成正比。

在这里插入图片描述

在这里插入图片描述

对于长度为N的数组,自顶向下的归并排序需要(1/2)*N*lgNN*lgN次比较。

6.自底向上的归并排序从长度为1的子数组开始,两两归并,结束后对长度为2的子数组进行四四归并。。。直到整个数组归并完成。

在这里插入图片描述

在这里插入图片描述

对于长度为N的任意数组,自底向上的归并排序需要(1/2)*N*lgNN*lgN次比较,最多访问数组6*N*lgN次。

当数组的长度为2的幂时,自顶向下和自底向上的归并排序所用的比较次数和访问数组的次数相同,只是顺序不同。自底向上的归并排序适合用链表组织的数据。

7.快速排序的优点是它是原地排序(只需要很小的辅助栈),将长度为N的数组排序所需的时间和N*lgN成正比。快速排序还是一种分治的排序算法。归并算法的递归调用发生在处理整个数组之前,而快速排序的递归调用在处理整个数组之后。该算法的重点在方法partition,它确定了j,a[lo]到a[j-1]的所有元素都不大于a[j],a[j+1]到a[hi]的所有元素都不小于a[j]。实际上递归调用的是方法partition。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

数组元素被打乱过,保持随机性是为了预测算法的运行时间,保持随机性的另一种方法是在partition方法中随机选择一个切分元素v。

将长度为N的无重复数组排序,快速排序平均需要~2*N*lnN次比较和1/6的交换,即使存在重复的元素,平均比较次数也不会大于~N*lgN。快速排序的缺点在于切分不平衡的时候可能比较低效,所以需要保证数组的随机性,在排序前将数组元素的顺序打乱(P186)。

快速排序最多需要约N^2/2次比较,但随机打乱数组能预防这种情况。对于大数组,运行时间是平方级别的概率极小,随着N的增大,运行时间会趋向于平均数也就是~2*N*lnN到~N*lgN

总之,对于大小为N的数组,算法2.5的运行时间在1.39*N*lgN的某个常数因子的范围之内,快速排序比归并排序更快。

8.需要对包含大量重复主键的数组排序时,三向切分的快速排序是最优的:

在这里插入图片描述

在这里插入图片描述

9.二叉堆是一组能够用堆有序的完全二叉树排序的元素,并在数组中按照层级储存(不使用数组的第一个位置,层级越小优先级越高)。在二叉堆的数组中,每个元素都要保证大于等于另两个特定位置的元素。当一棵二叉树的每个结点都大于等于它的两个子结点时(如果有的话),其是堆有序的。

10.注意学习由下至上的堆有序化(上浮)和由上至下的堆有序化(下沉)。对于一个含有N个元素的基于堆的优先队列,插入元素操作只需不超过(lgN+1)次比较,删除最大元素操作需要不超过2*lgN次比较。

11.将N个元素排序,堆排序只需少于(2*N*lgN+2*N)次比较以及一半次数的交换。2*N来源于堆的构造,2*N*lgN来源于每次下沉操作最大可能需要2*lgN次比较。

在这里插入图片描述

12.实现Comparable接口只需要定义一个compareTo函数(一个参数),并在其中定义该数据类型中的大小关系。

13.在java中,可以通过用不可变的数据类型(String,Integer,Double,File等)作为键来避免排序后用例还能修改键值。

14.可以通过构造实现Comparator接口的内部类(实现了方法compare,有两个参数)作为比较器,这样就可以为外部类进行多种类型的比较提供更灵活的实现。

15.如果一个排序算法能够保留数组中重复元素的相对位置则可以被称为是稳定的。在java中,一般对原始数据类型使用(三向切分的)快速排序,对引用类型使用归并排序。
在这里插入图片描述

16.找到第K小的元素代码,可以用于寻找中位数(不大于一半的元素,又不小于一半的元素),其中partition方法是快速排序中的切分,当k和数组的大小成比例的时候(如中位数)该方法select可以在线性时间内解决问题:

在这里插入图片描述

————————

第三章——查找

1.对于无序链表,向一个空表插入N个不同的键需要(~N^2/2)次比较(1+2+3+…+N = N(N+1)/2)。

2.数组的某个元素之后的元素需要集体往后挪动一个位置时,应该按照从后往前的顺序分别向后移动一个位置。

3.关于有序数组(元素个数为N)中的二分查找,递归的二分查找和算法3.2中if(hi<lo) return lo;意味着数组中不存在对应的键,有三种情况:(1)要查询的键key小于数组中所有元素,因为lo的初始值是0,随着递归或者循环的进行,hi会越来越小,直到小于lo,此时返回的lo值为0;(2)要查询的键key大于数组中所有元素,因为hi的初始值是N-1,随着递归或者循环的进行,lo会越来越大,直到大于hi,此时返回的lo值为N;(3)要查询的键key大于数组中的M个元素,但key不在数组中,可以将这种情况视为第二种情况的特殊形式,最后迭代或递归的时候hi的值为M-1,lo就是M。

4.二分查找所需时间必然在对数范围内。在N个键的有序数组中进行二分查找最多需要(lgN+1)次比较(无论是否成功)。

5.向大小为N的有序数组中插入一个新元素在最坏情况下需要访问~2*N次数组(新元素小于数组中所有元素时,key数组和value数组中的元素都要往后挪一位),因此向一个空符号表中插入N个元素在最坏情况下需要访问~N^2次数组(2*(1+2+…+N) = 2N(N+1)/2 = N(N+1) ~N^2)。

6.在二叉搜索树中插入节点时,需要沿着路径往上直到根节点更新每个节点的N值(该节点为根节点的子树的节点个数)或val值,只需要递归调用之后返回被更新的节点给节点对应的父节点即可,不需要另外存储当前节点的父节点,节省存储空间。

7.在由N个随机键组成的二叉查找树中,查找命中、插入操作和查找未命中平均所需的比较次数为~2lnN(约1.39lgN)。

8.在一棵二叉查找树中,所有操作(除了范围查找)在最坏情况下所需的时间都和树的高度成正比。

9.如果要在2-3树中插入新结点,需要和二叉查找树一样先进行一次未命中的查找,然后按照3.3.1节中规定的调整步骤进行调整(重点)。

10.在一棵大小为N的2-3树中,查找和插入操作访问的结点必然不超过lgN个。

11.对于任意2-3树,只要对结点进行转换,都可以派生出一棵二叉查找树。红黑树既是二叉查找树,也是2-3树(用红色左链接相连的两个2-结点表示3-结点)。

12.如果有一条红色的右链接需要被转化成左链接,这个操作被称为左旋转,其实就是将红色右链接两端的两个键中的较小者作为根结点变为将较大者作为根结点。右旋转和左旋转相反,将较大者作为根结点变为将较小者作为根结点。
在这里插入图片描述

在插入新的键时可以用旋转操作保证2-3树和红黑树之间的一一对应关系,因为旋转可以保证红黑树的两个重要性质:有序性和完美平衡性。

13.所有基于红黑树的符号表实现都能保证操作的运行时间为对数级别(范围查找除外)。

在这里插入图片描述

14.不同类型的键应该用不同的散列函数进行散列:

(1)将整数散列最常用的方法是除留余数法,需要选择大小为素数(2的幂除外)的数组。

(2)如果键是0至1之间的实数,可以将键表示为二进制数然后再使用除留余数法。

(3)在java中对字符串进行散列时使用和horner方法类似的方法,用N次乘法、加法和取余来计算一个字符串的散列值。

15.对于基于拉链法的、含有M条链表和N个键的散列表中,未命中查找和插入操作所需的比较次数为~N/M。这种数据结构适用于键的顺序并不重要的应用,无法实现和有序性相关的符号表操作。

16.基于线性探测法的散列表用大小为M的数组存储N个键值对(M>N),基于数组中的空位解决碰撞冲突,按照这种策略构成的散列表被称为开放地址散列表,这种散列表需要调整存储键和值数组的大小,避免散列表被填满时进入无限循环。

17.Java的java.util.TreeMap和java.util.HashMap分别是基于和红黑树和拉链法的散列表的符号表实现。

18.“索引”是一个键和多个值相关联的符号表。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本书带完整书签 第1章 基础 1 1.1 基础编程模型 4 1.1.1 Java程序的基本结构 4 1.1.2 原始数据类塑与表达式 6 1.1.3 语句 8 1.1.4 简便记法 9 1.1.5 数组 10 1.1.6 静态方法 12 1.1.7 API 16 1.1.8 字符串 20 1.1.9 输入输出 21 1.1.10 分査找 28 1.1.11 展望 30 1.2 数据抽象 38 1.2.1 使用抽象数据类型 38 1.2.2 抽象数据类型举例 45 1.2.3 抽象教据类型的实现 52 1.2.4 更多抽象数据类型的实现 55 1.2.5 数据类型的设计 60 1.3 背包、队列和栈 74 1.3.1 API 74 1.3.2 集合类數据类型的实现 81 1.3.3 链表 89 1.3.4 综述 98 1.4 算法分析 108 1.4.1 科学方法 108 1.4.2 观察 108 1.4.3 数学模型 112 1.4.4 增长数量级的分类 117 1.4.5 设计更快的算法 118 1.4.6 倍率实验 121 1.4.7 注意事项 123 1.4.8 处理对于输入的依赖 124 1.4.9 内存 126 1.4.10 展望 129 1.5 案例研究:union-find算法 136 1.5.1 动态连通性 136 1.5.2 实现 140 1.5.3 展望 148 第2章 排序 152 2.1 初级排序算法 153 2.1.1 游戏规则 153 2.1.2 选择排序 155 2.1.3 插入排序 157 2.1.4 排序算法的可视化 159 2.1.5 比较两种排序算法 159 2.1.6 希尔排序 162 2.2 归并排序 170 2.2.1 原地归并的抽象方法 170 2.2.2 自顶向下的归并排序 171 2.2.3 自底向上的归并排序 175 2.2.4 排序算法的复杂度 177 2.3 快速排序 182 2.3.1 基本算法 182 2.3.2 性能特点 185 2.3.3 算法改进 187 2.4 优先队列 195 2.4.1 API 195 2.4.2 初级实现 197 2.4.3 堆的定义 198 2.4.4 堆的算法 199 2.4.5 堆排序 205 2.5 应用 214 2.5.1 将各种數据排序 214 2.5.2 我应该使用啷种排序算法 218 2.5.3 问题的归约 219 2.5.4 排序应用一览 221 第3章查找 227 3.1 符号表 228 3.1.1 API 228 3.1.2 有序符号表 230 3.1.3 用例举例 233 3.1.4 无序链表中的顺序查找 235 3.1.5 有序數组中的分查找 238 3.1.6 对分査找的分析 242 3.1.7 预览 244 3.2 叉查找树 250 3.2.1 基本实现 250 3.2.2 分析 255 3.2.3 有序性相关的方法与删除操作 257 3.3 平衡査找树 269 3.3.1 2-3査找树 269 3.3.2 红黑叉查找树 275 3.3.3 实现 280 3.3.4 删除操作 282 3.3.5 红黑树的性质 284 3.4 散列表 293 3.4.1 散列函数 293 3.4.2 基于拉链法的散列表 297 3.4.3 基于线性探测法的散列表 300 3.4.4 调整教组大小 304 3.4.5 内存使用 306 3.5 应用 312 3.5.1 我应该使用符号表的哪种实现 312 3.5.2 集合的API 313 3.5.3 字典类用例 315 3.5.4 索引类用例 318 3.5.5 稀疏向量 322 第4章 图 329 4.1 无向图 331 4.1.1 术语表 331 4.1.2 表示无向图的数据类型 333 4.1.3 深度优先搜索 338 4.1.4 寻找路径 342 4.1.5 广度优先搜索 344 4.1.6 连通分量 349 4.1.7 符号图 352 4.1.8 总结 358 4.2 有向图 364 4.2.1 术语 364 4.2.2 有向图的数据类型 365 4.2.3 有向图中的可达性 367 4.2.4 环和有向无环图 369 4.2.5 有向图中的强连通性 378 4.2.6 总结 385 4.3 最小生成树 390 4.3.1 原理- 391 4.3.2 加权无向图的数据类型 393 4.3.3 最小生成树的API和测试用例 396 4.3.4 Prim算法 398 4.3.5 Prim算法的即时实现 401 4.3.6 Kruskal算法 404 4.3.7 展望 407 4.4 最短路径 412 4.4.1 最短路径的性质 413 4.4.2 加权有向图的数据结构 414 4.4.3 最短路径算法的理论基础 420 4.4.4 Dijkstra算法 421 4.4.5 无环加权有向图中的最短路径算法 425 4.4.6 一般加权有向图中的最短路径问题 433 4.4.7 展望 445 第5章 字符串 451 5.1 字符串排序 455 5.1.1 键索引计数法 455 5.1.2 低位优先的字符串排序 458 5.1.3 高位优先的字符串排序 461 5.1.4 三向字符串快速排序 467 5.1.5 字符串排序算法的选择 470 5.2 单词查找树 474 5.2.1 单词查找树 475 5.2.2 单词查找树的性质 483 5.2.3 三向单词查找树 485 5.2.4 三向单词查找树的性质 487 5.2.5 应该使用字符串符号表的哪种实现 489 5.3 子字符串查找 493 5.3.1 历史简介 493 5.3.2 暴力子字符串査找算法 494 5.3.3 Knuth-Morris-Pratt子字符串查找算法 496 5.3.4 Boyer-Moore字符串查找算法 502 5.3.5 Rabin-Karp指纹字符串查找算法 505 5.3.6 总结 509 5.4 正则表达式 514 5.4.1 使用正则表达式描述模式 514 5.4.2 缩略写法 516 5.4.3 正则表达式的实际应用 517 5.4.4 非确定有限状态自动机 518 5.4.5 模拟NFA的运行 520 5.4.6 构造与正则表达式对应的NFA 522 5.5 数据压缩 529 5.5.1 游戏规则 529 5.5.2 读写进制数据 530 5.5.3 局限 533 5.5.4 热身运动:基因组 534 5.5.5 游程编码 537 5.5.6 霍夫曼压缩 540 第6章背景 558 索引 611
个人觉得是我见过的最简单易懂的算法入门书籍。 以前搜刮过几本算法竞赛书,但是难度终归太大【好吧,其实是自己太懒了】。 略翻过教材,大多数水校的教材,大家懂的。好一点的也是那本国内的经典,不是说它写的不好,只是没有这一本好。 本书Java实现,配有大量的图解,没有一句难懂的话,而且全都是模块化实现。 讲的都是实用算法,没有那些高大上听着名字就让人感到很害怕的东西,个人觉得比CLRS实用性要强,更加适合入门的学习。 大一,推荐这本书入门 【有C语言基础即可,自己去搜索下如何用Java写出Hello World就没有问题】 大,推荐这本书从头到尾好好读一遍,做下上千道的课后习题 【后面的有点小难度,但是难度不大值得一做,听起来很多的样子,用心去做,相信很快就可以做完的】。 大三,推荐这本书,重新温习已知算法,为找工作,考研做准备。 【可以试着自己在纸上全部实现一遍】 大四,依旧推荐这本书,没事重温经典,当手册来查也不错。 Sedgwick 红黑树的发现者,Donald E.Knuth 的得意门生,对各种算法都有比较深入的研究,他的书,我想不会太差。 也许对于数据结构的学习涉及的内容比较少,没有动态规划,图论也只是讲了很基础的东西,字符串中KMP弄的过于复杂(对比于acm)。但是瑕不掩瑜,对于绝大部分内容真的讲的超级清楚,完美的图解,就像单步调试一样,也许是一本不需要智商就能看懂的算法书(习题应该略有难度,还没有做,打算上Princeton的公开课时同步跟进)。至少这是一本让我这个算法渣渣看了爱不释手,怦然心动的书。 完美学习资源: 官方主页:http://algs4.cs.princeton.edu/home/ Coursera公开课:https://www.coursera.org/course/algs4partI (听说已经开课两期了,最近即将开课的时间是2014/09/05号那期,希望有兴趣的同学一起来学习)。 MOOC平台(笔记、讨论等): http://mooc.guokr.com/course/404/Algorithms--Part-I/ http://mooc.guokr.com/course/403/Algorithms--Part-II/ 不得不吐槽,他的lecture比他的书好,他本人讲的课更是一绝。 互补课程: 斯福坦的Algorithms: Design and Analysis, http://mooc.guokr.com/course/157/Algorithms--Design-and-Analysis--Part-1/ 快毕业了才接触到豆瓣和MOOC,看到很多经典的书籍都是推荐大学一年级的学生看,每每想到自己却连书皮都没有摸过,就深感惭愧。 我们都老的太快,却聪明得太迟。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值