八大排序演算法(2)_快速排序的優化

YunShell發表於2014-04-04

        最經在看大話資料結構。本文中的優化內容基本是該書上的總結。程式碼可能有點不同。

       快速排序是21世紀經典的十大演算法之一。其思路為:選取一箇中樞元素,然後通過一種方法,在該序列中唯一確定了該中樞位置,即是前面的都小於該中樞值,後面的都比該中樞值大。從而將待排序列,分割成了兩半。當然這是最好的情況下,此時效果最好。下面從3方面來優化。

未經過優化的排序為:

void quicksort(int a[],int first,int last)
{
	if(first<last)
	{
		 int i=first,j=last; 
		 int tmp=a[first];
		 while( i<j )
		 {
			 while(i<j && a[j]>=tmp)
			 --j;		// find the first index j that a[j] < tmp from right to left
			 if(i<j)
				 a[i++]=a[j];		// cover the a[i]. 
			 while( i<j && a[i]<tmp)
				 i++;			//find the first index i that a[i]>tmp from left to right
			 if(i<j)
				 a[j--]=a[i];		//cover the a[j] 
		 }
		if(i==j)
			a[i]=tmp;
		quicksort(a,first,i-1);
		quicksort(a,i+1,last);
	}
}
缺點:

1.中樞值每次都選取為序列首元素。不能保證儘可能為中間值。

2.對於資料的排序而言,對於小資料而言,使用直接插入排序效果可能更好。

3.快速排序使用了兩個遞迴呼叫,能不能進一步優化。

優化 從3方面進行:

1.選取中樞值。這裡可以採用隨機的方法,但是產生隨機序列本身也要耗時,效果可能不好,從概率的角度來看,選取頭,中,尾三處的值。然後取中間值。作為中樞值,效果較好。

/***********************************************************************
QuickSort optimized
1. optimize base value
2. optimize sort scale n 
3. optimize the way of recusion (tail recursion)
***********************************************************************/
#include <iostream>
#include <ctime>
using namespace std;
void Swap(int &x,int &y)
{
	int tmp=x;
	x=y;
	y=x;
}
//Unoptimized QuickSort
void quicksort(int a[],int first,int last)
{
	while(first<last)
	{
		 int i=first,j=last; 
		 int mid=(first+last)/2; //mid value
		
		 if(a[first]>a[last])
			 Swap(a[first],a[last]); // ensure index pos=first value less than last
		 if(a[mid]>a[last])
			Swap(a[mid],a[last]);  // ensure index pos=mid value less than last
		 if(a[first]>a[mid])
			 Swap(a[first],a[mid]); // ensure first val less than mid
		 int tmp=a[first];  //now  a[first] is the mid-value of low -mid-high

		 while( i<j )
		 {
			 while(i<j && a[j]>=tmp)
				 --j;		// find the first index j that a[j] < tmp from right to left
			 if(i<j)
				 a[i++]=a[j];		// cover the a[i]. 
			 while( i<j && a[i]<tmp)
				 i++;			//find the first index i that a[i]>tmp from left to right
			 if(i<j)
				 a[j--]=a[i];		//cover the a[j] 
		 }
		if(i==j)
			a[i]=tmp;
		quicksort(a,first,i-1);
		first=i+1;			//reduce one recursion
		//quicksort(a,i+1,last);
	}
}

void QuickSort(int a[],int len)
{	
	if(len>32)
		quicksort(a,0,len-1);
	//else   // when data scale less than 32 use InsertSort
	//	InsertSort(a,len); 
}
void print(int a[],int len)
{
	for(int i=0;i<len;i++)
		printf("%d ",a[i]);
	printf("\n");
}
int main()
{
	srand(time(NULL));
	const int MAX=1000;
	int a[MAX];
	for(int i=0;i<MAX;i++)
		a[i]=rand();
	clock_t timebegin=clock();
	QuickSort(a,MAX);
	clock_t timeend=clock();
	//cout<<"優化排一千萬個數耗時:\t"<<timeend-timebegin<<"ms"<<endl;
	print(a,MAX);
}


相關文章