排序演算法c語言描述-快速排序隨機化
阿新 • • 發佈:2019-02-19
今天在做資料結構排序實驗的時候,使用的快速排序。按理,我印象中快排是很高效的,不過,這次400w的資料,排了2659秒,有點意想不到,讓我一度懷疑了演算法是否寫錯了。
不過,認真分析,認真想想後, 也就釋然了。
快排其實就是冒泡的升級版。
每次遞迴,把當前序列分成兩部分,一個比樞紐元素大,一個比樞紐元素小。具體思想可以參見的之前寫的一篇部落格。
http://blog.csdn.net/hitwhylz/article/details/9968639
至於這次實驗的低效,我看了下所給的資料,發現序列基本有序,從20-------3999997
排列的很有規則,就移動了些許位置, 但是保持遞增趨勢。
這樣的序列使用常規快排,那就體現不出快排的優勢了。 因為每次選取的時候都是 採用子序列的第一個元素為樞紐元素 int pivot = array[low];
這樣導致每次比較,分出的序列差別都很大,以至於需要遞迴很多次。
為解決這問題,採用了快速排序隨機化方法,即每次確定的樞紐元素都是隨機找出的。
一般來說隨機選取樞紐元這種策略非常安全,除非隨機數生成器有問題(這不像你所想象的那麼罕見),因為隨機的樞紐元不可能總在接連不斷地產生劣質的分割。
下面具體看程式碼了。
學習的路上,與君共勉。#include "stdio.h" #include "math.h" #include "stdlib.h" int num = 10; void swap(int *a,int *b) { int tmp; tmp = *a; *a = *b; *b = tmp; } void PrintArray(int arr[]) { int i; for(i=0; i < num; ++i) { printf("%d ", arr[i]); } } int Partition(int *arr, int beg, int end) { int j; int sentinel = arr[end]; int i = beg-1; for(j=beg; j <= end-1; ++j) { if(arr[j] <= sentinel) { i++; swap(&arr[i], &arr[j]); } } swap(&arr[i+1], &arr[end]); printf("\n排序過程:"); PrintArray(arr); return i+1; } int RandomPartition(int *arr, int beg, int end) { int i = beg + rand() % (end-beg+1); swap(&arr[i], &arr[end]); return Partition(arr, beg, end); } void RandomQuickSort(int *arr, int beg, int end) { if(beg < end) { int pivot = RandomPartition(arr, beg, end); printf("\n隨機選擇 arr[%d](%d)", pivot, arr[pivot]); RandomQuickSort(arr, beg, pivot-1); printf("\n隨機選擇 arr[%d](%d)", pivot, arr[pivot]); RandomQuickSort(arr, pivot+1, end); } } int main() { int i; int arr[10]; srand(time(0)); for(i=0; i < 10; i++) { arr[i] = rand()%100+1; //printf("%d ", rand()%100+1); } printf("初始陣列:"); PrintArray(arr); RandomQuickSort(arr, 0, num-1); printf("\n最後結果:"); PrintArray(arr); return 0; }