實現對陣列的普通快速排序與隨機快速排序。
(1)實現上述兩個演算法
(2)統計演算法的執行時間
(3)分析效能差異,作出總結
(一)快速排序
通過使用分治思想對快速排序演算法進行描述。下面對乙個典型的子陣列a[p…r]進行快速排序的三步分治過程:
分解:陣列a[p…r]被劃分為兩個(可能為空)子陣列a[p…q-1]和a[q+1…r],使得a[p…q-1]中的每乙個元素都小於等於a[q],而a[q]也小於等於a[q+1…r]中的每個元素。其中,計算下標q也是劃分過程的一部分。
解決:通過遞迴呼叫快速排序,對於陣列a[p…q-1]和a[q+1…r]進行排序。
合併:因為子陣列都是原址排序的,所以不需要合併操作:陣列a[p…r]已近有序。
關鍵**實現:
(一)實現快速排序:
quicksort(a,p,r)
1 if p < r
2 q = partition(a,p,r)
3 quicksort(a,p,q-1)
4 quicksort(a,q+1,r)
(二)陣列的劃分:
partition(a,p,r)
1 x = a[r]
2 i = p-1
3 for j = p to r-1
4 if a[j] <= x
5 i = i + 1
6 exchange a[i]with a[j]
7 exchange a[i+1] with a[r]
8 return i+1
(二)隨機快速排序
隨機快速排序與始終採用a[r]作為主元的方法不同,通過採用一種隨機抽樣的隨機化技術,使得從子陣列a[p…r]中隨機選擇乙個元素作為主元。為達到這一目的,首先將a[r]從a[p…r]中隨機選出的乙個元素交換。通過對序列p,…,r的隨機抽樣,我們可以保證主元元素x=a[r]是等概論地從子陣列的r-p+1個元素中選取的,由於主元素是隨機選取的,使得對輸入陣列的劃分也是比較均衡的,從而獲得較好的期望效能。
關鍵**實現:
(一)隨機數組的呼叫:
randomized-partition(a,p,r)
1 i = random(p,r)
2 exchange a[r] with a[i]
3 return partition(a,p,r)
(二)函式partition(a,p,r)仍呼叫快速排序的partitoon(a,p,r)函式
說明:快速排序過程中,呼叫quicksort()和partition()函式進行陣列內部的快速排序;對於隨機快速排序,則呼叫randomized-partition()來選取隨機的關鍵字(key),再通過quicksort()和partition()函式進行排序。
10個元素快速排序的實驗結果:
10000個元素快速排序的實驗結果:
10個元素隨機快速排序的實驗結果:
10000個元素隨機快速排序的實驗結果:
(一)從原理上分析,快速排序的最壞執行時間是θ(n2),即在每次進行partition(a,p,r)函式對陣列a進行劃分時,都出現主元素在劃分區域的某一側,使得劃分區域的元素都小於或大於主元素;期望執行時間是θ(nlgn),在隨機快速排序中,執行randomized_partition(a,p,r)後每次選取主元素都能使得主元素在劃分區域的中間。
(二)從實際的執行過程中,實驗隨機生成10、10000個資料進行排序,並比較了執行排序**的時間。實驗出現中,執行時間未出現較大區分度的原因:一方面是因為在普通快速排序過程中,陣列是隨機生成的,這樣使得在每次選取主元時,和隨機快速排序相似,從而二者區分度不高;另一方面,電腦主頻較高、選取的實驗資料不夠大也會使二者區分度不高。
附錄(**)
(一)普通快速排序
#include #include(二)隨機快速排序#include
#define max 10000
#define clocks_pre_sec ((clock_t)1000)
void quicksort(int array, int p, intr)}
int partition(int array, int p, int
r) }
m =array[i+1
]; array[i+1] =array[r];
array[r] =m;
return (i+1);}
intmain()
printf(
"\nquicksortresult:\n");
start =clock();
quicksort(array,
0 ,max-1
); finish =clock();
for(i = 0; i< max; i++)
printf(
"%d\n
",array[i]);
thetimes =(double)((finish - start)/clocks_pre_sec);
printf(
"thetime of quicksort is:%fs!\n
",thetimes);
}
1 #include 23 #include 4
5 #include 678
9#define max 1000
1011
#define clocks_pre_sec ((clock_t)1000)
1213
1415
int random_partition(int array, int p, int
r)16
1734
3536
37void random_quicksort(int array, int p, int
r)38
395455}
5657
5859
int partition(int array, int p, int
r)60
618687}
8889 m =array[i+1
];90
91 array[i+1] =array[r];
9293 array[r] =m;
9495
9697
return (i+1
);9899}
100101
102103
intmain()
104105
128129 printf("
random_quicksortresult:\n");
130131
132133 start =clock();
134135 random_quicksort(array,0 ,max-1
);136
137 finish =clock();
138139
140141
for(i = 0; i< max; i++)
142143 printf("
%d\n
",array[i]);
144145 thetimes = (double)((finish- start)/clocks_pre_sec);
146147 printf("
thetime of random_quicksort is:%fs!\n
",thetimes);
148149 }
快速排序和隨機快速排序
嚴書上的快排是以最左邊元素為樞紐的,如下 include include using namespace std intpartition int a,int left,int right a left p return left void quicksort int a,int left,int ...
隨機快速排序
問題畫出來小於區域和等於區域,劃偏 1,2,3,4,5,6,7 7 7 總拿最後乙個劃分,跟資料狀況有關,比較差的蛻變程o n 2 6,5,4,3,2,1 1,1 資料分布比較差 比價好的情況 x t n 2t n 2 o n n nlogn 隨機快速排序 隨機選擇乙個數和最後乙個替換一下 長期期望...
經典快速排序演算法與隨機快速排序演算法
快速排序用到了分治思想,同樣的還有歸併排序。乍看起來快速排序和歸併排序非常相似,都是將問題變小,先排序子串,最後合併。不同的是快速排序在劃分子問題的時候經過多一步處理,將劃分的兩組資料劃分為一大一小,這樣在最後合併的時候就不必像歸併排序那樣再進行比較。但也正因為如此,劃分的不定性使得快速排序的時間複...