Solution to CLRS Chapter 7

来源:互联网 发布:走遍中国中国古镇 知乎 编辑:程序博客网 时间:2024/06/05 19:47

7-1.1
0: 13,19,9,5,12,8,7,4,21,2,6,11
1: 9,19,13,5,12,8,7,4,21,2,6,11
2: 9,5,13,19,12,8,7,4,21,2,6,11
3: 9,5,8,19,12,13,7,4,21,2,6,11
4: 9,5,8,7,12,13,19,4,21,2,6,11
5: 9,5,8,7,4,13,19,12,21,2,6,11
6: 9,5,8,7,4,2,19,12,21,13,6,11
7: 9,5,8,7,4,2,6,12,21,13,19,11
8: 9,5,8,7,4,2,6,11,21,13,19,12
return 8

7-1.2
返回结果是r
只要先特判一遍,如果全部相等就取一半。

7-1.3
n的复杂度,主要就是来自于j的遍历

7-1.4
基本上每一种排序都会出这道题目,也许理解一个排序算法的核心,就是弄清楚他的大小分配吧。只要把LINE4的小于等于改成大于等于就可以了。

7.2-1
这题也不用substitution method,展开就能够看出来是n^2的复杂度。

7.2-2
由于之前的练习给了一个调整,所以在所有元素相同的情况下,复杂度应该是标准的nlog(n)

7.2-3
这个也比较简单,主要就是想表达quicksort的worst case 就是n^2的复杂度。如果是递减的话,每次partition都只能够把数组长度减少1,从而形成严重不平衡,时间复杂度变成了7.2-1中的那个公式。

7.2-4
这题定性分析,在一个数组几乎已经排好序的情况之下,用insertion sort的复杂度是十分接近线性的,但是quicksort的复杂度很高,根源就在于quicksort在遇到已排序数组的时候,partition过程会生成不平衡的划分,导致quicksort出现worst case。所以银行工作人应该采用的是insertion sort,应该不会有人去用quick sort去排序,就算他们知道这个算法也不会去用。

7.2-5
这个不是显而易见的么,a个儿子的树高度应该是log(n)/log(a)。。。

7.2-6
这个是一个数学题。比较复杂的数学题,对算法本身的理解似乎没有什么帮助,跳过了。

7.3-1
因为没有什么input能够让算法达到worst case,同时所有的input都可能让算法达到worst case,所以worst case没有意义,因为不存在这样的case

7.3-2
由于Random和Partition 是绑定的,所以Random的调用次数就是partition的调用次数,那么这道题其实就是之前的题目,问最坏最好的情况。没什么难度。调用n次和log(n)次

Problem

7-1 Hoare partition correctness
(a)
0: 13,19,9,5,12,8,7,4,11,2,6,21 i=0,j=13,x=13
1: 6,19,9,5,12,8,7,4,11,2,13,21 i=1,j=11
2: 6,2,9,5,12,8,7,4,11,19,13,21 i=2,j=10
3: 6,2,9,5,12,8,7,4,11,19,13,21 i=10,j=9
return 9
一开始我对这个结果挺疑惑的,不理解为什么返回9因为13不在9这个位置,后来发现这个算法的目的只是把序列分开来,至于划分的标准,没有必要在划分点。。
(b)
证明i,j绝对不会越界。
证明,第一次i和j必然能够在A[p]停下来(这个是由循环判断中的等号保证的),这个时候,直接返回。这个情况的意思是,如果i,j停下来之前,没有做任何的交换,那么它们也不会越界。
那剩下的情况,就只是:i,j在停下来之前,做了交换,比如分别在A[x],A[y]的位置,那么j最起码一定会在交换后的x处停止,i同理!!这个部分我觉得无比奇妙,达到这个效果,仅仅只是在判断条件中,添加了一个等号!!
(c)
证明划分停止时,j在区间内,而且j不在r处。
这个根据上面的结论一定得出j在区间内,j不在r处的意思,就是说这个划分一定能保证数组在变小,那么为什么j不在r处呢?其实很简单,如果j在r停止,而i必然在p停止一次,两者交换后,j必须移向r-1,告别了r
(d)
循环不变量来证明循环的正确性,在我看来其实是提供一种机械的手段,来确保自己算法的正确性。这个循环不变量的成立很显然。
(e)
这里有一个细节,注意到之前给出的算法,经过划分之后,保证划分点一定是已经排好序了的,但是Hoare不能保证这一点!

RANDOMIZED-QUICK-SORT(A, p, r)        if p < r                q = RANDOM-PARTITION(A, p, r)                RANDOMIZED-QUICK-SORT(A, p, q+1)                RANDOMIZED-QUICK-SORT(A, q+1, r)RANDOM-PARTITION(A, p, r)        i = RANDOM(p, r)        swap(A[i], A[p])        HOARE-PARTITION(A, p, r)HOARE-PARTITION(A, p, r)        j = r + 1        i = p - 1        x = A[p]        while true                do                         j = j - 1                until A[j] <= x                do                         i = i + 1                until A[i] >= x                if i < j                        swap(A[i], A[j])                else                        return j

7-2 Quicksort with equal element values
这道题考虑当数组中出现相同的元素的时候,quicksort的效率如何。为什么排序算法会对元素是否相同敏感呢?就quicksort而言,由于划分的平衡性决定了quicksort的效率,而元素相同的情况很容易就导致了书上的划分方式的worst case(不过相同元素能够使得Hoare划分最优)
(a)
如果元素全部都是相同的话,RANDOMIZED-PARTITION并没有什么用,怎么随机都改变不了1,n-1的划分。running time 显然就是N
(b)
这里要求实现一个划分,将数组划分成三段:小于x,等于x,大于x。这样一来,中间的部分,也就是全x的部分,天生就是排序完毕的。这样如果相同元素很多的话,就大大减少的复杂度!
那么怎么去实现这样一个个划分呢?我是这么想的:
如果把所有比x小的放在数组前面,把所有比x大的放在数组后面,那么中间的部分就自然而然的是x!这个实现起来很简单,只要用两个下标指针来标记大小范围就可以了。

NEW-PARTITION(A, p, r)        i = p - 1        j = r + 1        x = A[r]        for k = p : r                if A[k] < x                        i = i + 1                        swap A[i], A[k]                elseif A[k] > x                        j = j - 1                        swap A[j], A[k]        return i, j

(c)
发现自己坐上面一道题的时候已经考虑完这道题要考虑的意思了。

7-4 Stack depth for quicksort
这题指出在QuickSort中其实可以只调用一次自身就能够完成,并且引入了tail-recursion的方法
(a)
证明那个算法是正确的,由于用的是循环,所以从循环不变量的角度去考虑
Initialization:
最开始的时候,p=1,q=n,所以p之前的元素当成是有序的。
Maintenance:
假设循环前,p之前的数组一定是有序的,那么循环之后,p之前的数组一定也有序,因为p,r是一个正确的划分,那么q之前的数一定比q小,那么调用了递归对q之前的数排序后,并不影响它们和q之间的兼容,所以q之前的数有序,从而p之前的数有序,性质维持。
Termination:
结束的时候p >= r这时p之前的数有序,所以整个数组有序。

(b)
题意是设想一个最糟糕的情况,让tail-recursive-quicksort的栈的深度达到N.这个其实就是QS的最坏划分啦,就每次分离一个元素。比如,若是用书中正文的划分程序,那么所有元素都相同就可能导致这种划分。

(c)
这题要你调整尾递归的QS代码,使得最大栈深度是log(n).
这题其实我不是很有把握,根据题目的expected running time,所以我考虑的方向是用随机划分代替这里的普通划分。

7-5 Median-of-3 partition
Median-of-3是对QuickSort的一个常数级的优化,算法本身很简单,就是在划分时,选取3个随机数,然后从中选择三者的中位数。

7-6 Fuzzy sorting of intervals
模糊排序。这题是对几个区间的模糊排序,除非两个区间互斥,否则他们的大小可以随意改变。
这题可能是有实际意义的,但我不是很清楚。这个也比较简单,之前的QS的题目里面有一个是判断和x相等的值有多少个,可以直接用那个算法,也就是说,判断两个区间是否有重叠,如果有,那么就当作是“相同的数”,这样一来,如果区间全部重叠的话,那么就是QS全部相同的值,区间划分在第一次就是0 n 0分配,时间复杂度n

0 0
原创粉丝点击