1. 程式人生 > >排序演算法c語言描述-快速排序隨機化

排序演算法c語言描述-快速排序隨機化

今天在做資料結構排序實驗的時候,使用的快速排序。按理,我印象中快排是很高效的,不過,這次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;
}
學習的路上,與君共勉。