《算法导论》第七章----快速排序(代码实现+部分练习+部分证实)

《算法导论》学习记录目录html

快速排序,对于n个数的输入数组,最坏状况运行时间:Θ(n^2);指望运行时间:Θ(nlgn);就地排序(Sort in place)。算法

数组A[p..r]会被分为两个子数组A[p..q-1]和A[q+1..r],其中A[p..q-1]的元素都不大于A[q],A[q+1..r]都不小于A[q]。数组

如何划分子数组对运行时间的有很大影响,最坏的状况为n个数的数组划分为一个n-1的数组和一个0元素的数组;最佳状况为对半分(1:1);对于平均状况的划分,其运行时间与最佳状况很接近。dom

先看代码实现:ide

快速排序的关键是数组划分,对子数组进行就地重排。函数

 1 /*
 2  * 调用划分函数,使得子数组顺序重排
 3  */
 4 void quick_sort(int A[], int p, int r){
 5     if(p < r){
 6         int q = partition(A, p, r);
 7         quick_sort(A, p, q-1);
 8         quick_sort(A, q+1, r);
 9     }
10 }
11 
12 /*
13  * 对于比x值小的元素经过交换放置到小于x值的区域。
14  * 最后将大于x值的区域的第一个元素与x值,即原A[r],交换
15  * 该下标即为q,造成两个符合要求的数组(A[p..q-1]的元素都不大于A[q],A[q+1..r]都不小于A[q])
16  */
17 int partition(int A[], int p, int r){
18     int x = A[r];
19     int i = p - 1;
20     int j;
21     for(j = p; j <= r-1; j++){
22         if(A[j] <= x){
23             i++;
24             int temp = A[i];
25             A[i] = A[j];
26             A[j] = temp;
27         }
28     }
29     int temp = A[i+1];
30     A[i+1] = A[r];
31     A[r] = temp;
32     return i+1;
33 }
View Code

其中partition的运行时间为Θ(n),n = r-p+1,循环的次数为r-1-p;性能

过程图以下:学习

 

练习7.1-2ui

当数组A[p..r]中的元素均相同时,partition返回的q值是多少?修改partition,使得数组A[p..r]中的元素均相同时, q = floor((p+r)/2)spa

当数组A[p..r]中的元素均相同时,partition返回的q值是r;修改很简单,直接判断返回的q值是否与r相同,相同就返回 floor((p+r)/2)。

经网友提醒这种方法判断元素是否所有相同存在错误。。。。。往后再补上。。。囧。。。。 

 

快速排序的性能

快速排序的运行时间与划分数组是否对称有关。若是划分是对称,从渐近意义上讲,与合并排序同样快,不然就与插入排序同样慢。

最坏状况为划分一个n-1个元素的子数组和一个0个元素的子数组。(最大程度不对称)。划分运行时间为Θ(n)。若是对一个0个元素的数组进行递归调用,运行时间为Θ(1).

递归式为:T(n) = T(n-1) + T(0) + Θ(n) = T(n-1) + Θ(n)。经过代换法可证实T(n) = Θ(n^2) (练习7.2-1)

证实:先假设C1(n-1)^2 <= T(n-1) <= C2(n-1)^2成立

   则C1(n-1)^2 + Θ(n) <= T(n-1) + Θ(n) <= C2(n-1)^2 + Θ(n)

   C1n^2 -C1(2n - 1) + Θ(n) <= T(n-1) + Θ(n) <= C2n^2 -C2(2n - 1) +  Θ(n)

   咱们能够选择合适的常数C1、C2使得C1(2n - 1)、C2(2n - 1)支配Θ(n)。所以能够得出T(n) = Θ(n^2)。

注意,当输入数组彻底排好序(升降序同样)和全部元素都是相同的值时,运行时间为Θ(n^2),由于每次划分都是最大程度不对称。画画图,过一遍就会知道。

最佳状况为划分的两个子数组大小为floor(n/2)和ceiling(n/2)-1。

递归式为:T(n) <= 2T(n/2) + Θ(n)。该递归式的解为:T(n) = O(nlgn)

直接经过主定理的状况2得出。

平均状况运行时间更接近最佳状况而不是最坏状况。任一种按常数进行划分都会产生深度为Θ(lgn)的递归书,每一层的总代价为O(n),所以运行时间为O(nlgn)。

从下图看能够更加明显

最坏状况的划分以后最佳状况划分的总代价与直接最佳状况的总代价都为Θ(n)。

练习7.2-5

假设快速排序的每一层,所作划分比例都是1-a:a,其中0<a<=1/2是个常数。证实:在对应的递归树中,叶结点的最小深度大约是-lgn/lga,最大深度大约是-lgn/lg(1-a)。

最小深度为每次划分后都是选择最小的一部分继续往下走,每次乘以a。一次迭代减小的元素数从n到an,迭代m次直到剩下的元素为1。

则(a^m)*n = 1, a^m = 1/n,取对数得mlga = -lgn,m = -lgn/lga。

同理可得((1-a)^M)*n = 1,M = -lgn/lg(1-a)。

 

快速排序随机化版本

便于对于全部输入,均能得到较好的平均状况性能。

 1 int randomized_partition(int A[], int p, int r){
 2     int i = p + rand() % (r - p + 1);
 3     int temp = A[r];
 4     A[r] = A[i];
 5     A[i] = temp;
 6     return partition(A, p, r);
 7 }
 8 
 9 int partition(int A[], int p, int r){
10     int x = A[r];
11     int i = p - 1;
12     int j;
13     for(j = p; j <= r-1; j++){
14         if(A[j] <= x){
15             i++;
16             int temp = A[i];
17             A[i] = A[j];
18             A[j] = temp;
19         }
20     }
21     int temp = A[i+1];
22     A[i+1] = A[r];
23     A[r] = temp;
24     return i+1;
25 }
26 
27 void randomized_quick_sort(int A[], int p, int r){
28     if(p < r){
29         int q = randomized_partition(A, p, r);
30         randomized_quick_sort(A, p, q-1);
31         randomized_quick_sort(A, q+1, r);
32     }
33 }
View Code

练习7.3-2

在randomized-quicksort的运行过程当中,最坏状况下对随机数产生器random调用了多少次?最佳状况调用了多少次?

都为Θ(n)。

 

快速排序的分析

算导关于快排分析得很详细,数学太差了,看了不少遍才明白一点点,往后必定要继续努力,争取用本身的语言表达出来。

 

练习7.4-2

证实:快速排序的最佳状况运行时间为Ω(nlgn)

 

Hoare划分快速排序

划分方式有些不同;前面的partition划分是将主元值与围绕它划分造成的两部分分隔开来。而Hoare划分则老是将主元值放入到两个划分的子数组里。

 1 int hoare_partition(int A[], int p, int r){
 2     int x = A[p];
 3     int i = p;
 4     int j = r;
 5 
 6     while(i < j){
 7         while(i < j && A[j] > x)
 8             j--;
 9         A[i] = A[j];
10         while(i < j && A[i] < x)
11             i++;
12         A[j] = A[i];
13     }
14     A[i] = x;
15     return j;
16 }
17 
18 void hoare_quick_sort(int A[], int p, int r){
19     if(p < r){
20         int q = hoare_partition(A, p, r);
21         hoare_quick_sort(A, p, q-1);
22         hoare_quick_sort(A, q+1, r);
23     }
24 }
View Code

 

继续努力。。。

相关文章
相关标签/搜索