摘要: 2.3.22快速三向切分。(J.Bently,D.McIlroy)用将重复元素放置于子数组两端的方式实现一个信息量最优的排序算法。使用两个索引p和q,使得a[lo..p-1]和a[q+1..hi]的元素都和a[lo]相等。使用另外两个索引i和j,使用a[p..i-1]小于a[lo],a[j+1..q 阅读全文
posted @ 2018-10-27 10:03 修电脑的龙生 阅读(794) 评论(1) 推荐(0) 编辑
摘要: 2.3.21重复元素排序的比较次数下界。完成命题M的证明的第一部分。参考命题I的证明并注意当有k个主键值时所有元素存在N!/f1!f2!...fk!种不同的排列,其中第i个主键值出现的频率为fi(即NPi,按照命题M的记法),且f1+...fk=N。答:命题M。不存在任何基于比较的排序算法能够保证在 阅读全文
posted @ 2018-10-27 10:02 修电脑的龙生 阅读(374) 评论(0) 推荐(0) 编辑
摘要: 2.3.20非递归的快速排序。实现一个非递归的快速排序,使用一个循环来将弹出栈的子数组切分并将结果子数组重新压入栈。注意:先将较大的子数组压入栈,这样就可以保证栈最多只会有lgN个元素。public class E2d3d20{ //一个用记录子数组开始与结束索引的类 private class A 阅读全文
posted @ 2018-10-27 10:00 修电脑的龙生 阅读(261) 评论(0) 推荐(0) 编辑
摘要: 2.3.19附加题:找到一种对于任意输入都只需要少于7次比较的五取样算法。答:设有5个数,a,b,c,d,e,若这5个数有序,那么中位数为c,c的特点是它只大于两个数。设a,b,c,d,e为任意排列情况,按下面的步骤可以在6次比较时得到中位数1)用d与e比较,当d>e时,交换d,e得到d<e。2) 阅读全文
posted @ 2018-10-27 09:59 修电脑的龙生 阅读(315) 评论(0) 推荐(0) 编辑
摘要: 2.3.19五取样切分。实现一种基于随机抽取子数组中5个元素并取中位数进行切分的快速排序。将取样元素放在数组的一侧以保证只有中位数元素参与了切分。运行双倍测试来确定这样改动的效果,并和标准的快速排序以及三取样切分的快速排序(请见上一道练习)进行比较。附加题:找到一种对于任意输入都只需要少于7次比较的 阅读全文
posted @ 2018-10-27 09:56 修电脑的龙生 阅读(378) 评论(0) 推荐(0) 编辑
摘要: 2.3.18三取样切分。为快速排序实现正文所述的三取样切分(参见2.3.3.2节)。运行双倍测试来确认这项改动的效果。public class E2d3d18{ public static void sort(Comparable[] a) { StdRandom.shuffle(a); sort( 阅读全文
posted @ 2018-10-27 09:55 修电脑的龙生 阅读(829) 评论(0) 推荐(1) 编辑
摘要: 2.3.17哨兵。修改算法2.5,去掉内循环while中的边界检查。由于切分元素本身就是一个哨兵(v不可能小于a[lo]),左侧边界的检查是多余的。要去掉另一个检查,可以在打乱数组后将数组的最大元素放在a[length-1]中。该元素永远不会移动(除非和相等的元素交换),可以在所有包含它的子数组中成 阅读全文
posted @ 2018-10-27 09:54 修电脑的龙生 阅读(576) 评论(0) 推荐(0) 编辑
摘要: 2.3.16最佳情况。编写一段程序来生成使算法2.5中的sort()方法表现最佳的数组(无重复无素):数组大小为N且不包含重复元素,每次切分后两个子数组的大小最多差1(子数组的大小与含有N个相同元素数组的切分情况相同)。(对于这道练习,我们不需要在排序开始时打乱数组。)以下练习描述了快速排序的几个变 阅读全文
posted @ 2018-10-27 09:52 修电脑的龙生 阅读(396) 评论(0) 推荐(0) 编辑
摘要: 2.3.15螺丝和螺帽。(G.J.E.Rawlins)假设有N个螺丝和N个螺帽混在一堆,你需要快速将它们配对。一个螺丝只会匹配一个螺帽,一个螺帽也只会匹配一个螺丝。你可以试着把一个螺丝和一个螺帽拧在一起看看谁大,但不能直接比较两个螺丝或者两个螺帽。给出一个解决这个问题的有效方法。1) 将螺丝与螺帽分 阅读全文
posted @ 2018-10-27 09:50 修电脑的龙生 阅读(447) 评论(0) 推荐(0) 编辑
摘要: 2.3.14证明在用快速排序处理大小为N的不重复数组时,比较第i大和第j大元素的概率为2/(j-i),并用该结论证明命题K。 证:设数组子集Zij={Zi,Zi+1,Zi+2,....Zj}并且Zi<Zi+1<Zi+2<...<Zj。 由于元素只与切分元素进行对比 1)当切分元素V为Zi+1...至 阅读全文
posted @ 2018-10-27 09:49 修电脑的龙生 阅读(392) 评论(0) 推荐(0) 编辑
摘要: 2.3.12按照代码所示轨迹的格式给出信息量最佳的快速排序第一次是如何切分数组BABABABACADABRA的。答:即为Dijkstra三向切分快速排序的轨迹, 这种方式在大交换时可能会出现大值与大值交换的情况,这样又会多一次交换。 2.3.12按照代码所示轨迹的格式给出信息量最佳的快速排序第一次是 阅读全文
posted @ 2018-10-27 09:46 修电脑的龙生 阅读(221) 评论(0) 推荐(0) 编辑
摘要: 2.3.13在最佳、平均和最坏情况下,快速排序的递归深度分别是多少?这决定了系统为了追踪递归调用所需的栈的大小。在最坏情况下保证递归深度为数组大小的对数级的方法请见练习2.3.20。答:令排序数组长度为n1)最佳情况下,每次切分都能使左右子数组长度相同,递归深度为lgN。2)平均情况下,递归深度为l 阅读全文
posted @ 2018-10-27 09:46 修电脑的龙生 阅读(1325) 评论(0) 推荐(0) 编辑
摘要: 2.3.11假如在遇到和切分元素重复的元素时我们继续扫描数组而不是停下来,证明使用这种方法的快速排序在处理只有若干种元素值的数组时的运行时间是平方级别的。答:在有重复元素的情况下,一轮比较与交换后,与切分元素同值的元素仍就保持在原有位置,切分元素移动到分界位置,得到的排序结果为左子数组<=切分元素< 阅读全文
posted @ 2018-10-27 09:45 修电脑的龙生 阅读(454) 评论(0) 推荐(0) 编辑
摘要: 2.3.10Chebyshev不等式表明,一个随机变量的标准差距离均值大于k的概率小于1/k^2。对于N=100万,用Chebyshev不等式计算快速排序所使用的比较次数大于1000亿次的概率(0.1N^2)。答:4.225*10^-9切比雪夫不等式:P(|X-E(X)|>=r)<=V(X)/r^2 阅读全文
posted @ 2018-10-27 09:43 修电脑的龙生 阅读(220) 评论(0) 推荐(0) 编辑
摘要: 2.3.9请说明Quick.sort()在处理只有两种主键值的数组时的行为,以及在处理只有三种主键值的数组时的行为。1)两种主键值时1.1)小元素作为分界元素,子数组剩余的元素两端也是小元素时,会进行一次交换,这是不必要的交换,这个在有重复值时也会出现这种不必要的交换。1.2)大元素作为分界元素,子 阅读全文
posted @ 2018-10-27 09:40 修电脑的龙生 阅读(407) 评论(0) 推荐(0) 编辑
摘要: 2.3.8Quick.sort()在处理N个全部重复的元素时大约需要多少次比较?答:N(lgN-1)-lgN,一个更精确试验数据是:N(lgN-1)+2,目前没法分析出这个结果。1)对于每个元素个数大于1的子数组,数组的第一个元素作为分界元素,然后从第二个元素和最后一个元素开始向中间移动,当左右两指 阅读全文
posted @ 2018-10-27 09:39 修电脑的龙生 阅读(620) 评论(0) 推荐(0) 编辑
摘要: 2.3.6编写一段代码来计算Cn的准确值,在N=100、1000和1000的情况下比较准确值和估计值2NlnN的差距。public class E2d3d6{ static int Cn=0; public static void sort(Comparable[] a) { Cn=0; StdRa 阅读全文
posted @ 2018-10-27 09:38 修电脑的龙生 阅读(360) 评论(0) 推荐(0) 编辑
摘要: 2.3.7在使用快速排序将N个不重复的元素排序时,计算大小为0、1和2的子数组的数量。如果你喜欢数学,请推导;如果你不喜欢,请做一些实验并提出猜想。答:设使用快速排序的数组长度为N。将数组一分为二时之前的分界元素不在这两个子数组中,所以两个子数组的总长度为N-1。归纳得出第i层的所有子数组中的元素总 阅读全文
posted @ 2018-10-27 09:38 修电脑的龙生 阅读(286) 评论(0) 推荐(0) 编辑
摘要: 2.3.4假如跳过开头打乱数组的操作,给出六个含有10个元素的数组,使得Quck.sort()所需的比较次数到达最坏情况。答:有最多次比较,就要求每次切分后的左子数组 或 右子数组最长,也就是左子数组为空 或 右子数组为空。这样的排列满足关系式V1<V2<V3…<Vn 或 V1>V2>V3…>Vn 阅读全文
posted @ 2018-10-27 09:36 修电脑的龙生 阅读(565) 评论(0) 推荐(0) 编辑
摘要: 1)从数组两端向中间找到第一对不同的值,然后将大值作为分界值。2)从数组两端向中间找,左端找到等于大值时停止找,右端找到小于大值时停止找。3)交换上面找到的两个值。4)如此反复第2、第3步,直到中间相遇时结束。注意:如果数据只有一种值时,代码不能正确运行。public class E2d3d5{ p 阅读全文
posted @ 2018-10-27 09:36 修电脑的龙生 阅读(669) 评论(0) 推荐(0) 编辑