1. 程式人生 > >第七章快速排序之“快速插入排序”(練習7.4-5)

第七章快速排序之“快速插入排序”(練習7.4-5)

O(∩_∩)O~,這個名字乍聽起來比較黃。其實就是先快速排序進行劃分,等劃分小到一定規模比如k時,進行插入排序,因為規模小到一定程度,插入排序的效率更高。我在前面還寫過一個合併插入排序的演算法,思想跟這個相似。

總的時間複雜度為O(nk+nlg(n/k)),這個很好證明:
先進行二分,劃分到規模都為K時停止劃分,此時深度為h,則T(n/2^h)=k,則h=lg(n/k),最底層規模為K的葉節點數目為2^lg(n/k)=n/k,每個k內部插入排序,最壞情況為O(k^2),則總的插入排序時間為(n/k)*(k^2)=nk。每一層的劃分耗費為n,一共需劃分lg(n/k)層,耗費為O(nlg(n/k))。則總的時間複雜度是兩者相加共O(nk+nlg(n/k))。

程式碼如下:

#include <string.h>
#include <time.h>

#define BUFFER_SIZE 10

int Partition(int *a,int p,int r)
{
	int i=0;
	int j=0;
	int tmp=0;
	int x=0;
	
	i=p-1;
	x=a[r];
	for(j=p;j<r;j++)
	{
		if(a[j]<=x)
		{
			i++;
			tmp=a[i];
			a[i]=a[j];
			a[j]=tmp;
		}
	}
	tmp=a[i+1];
	a[i+1]=a[r];
	a[r]=tmp;
	
	return i+1;
}

int RandomPartition(int *a,int p,int r)
{
	int i=0;
	int tmp=0;
	
	srand((unsigned)time(NULL));
	i=rand()%(r-p+1)+p;
	
	tmp=a[i];
	a[i]=a[r];
	a[r]=tmp;
	
	return Partition(a,p,r);
}

void InsertionSort(int *a,int p,int r)
{
	int n=r-p+1;
	int b[n];
	int i=0;
	int j=0;
	
	b[0]=a[p];
	for(j=p+1;j<=r;j++)
	{
		i=j-1;
		while(i>=0&&a[j]<=b[i])
		{
			b[i+1]=b[i];
			i--;
		}
		b[i+1]=a[j];
	}
	for(j=p,i=0;j<=r;j++)
	{
		a[j]=b[i];
		i++;
	}
}

void RandomQuickSort(int *a,int p,int r,int k)
{
	int q=0;
	if(p>=r)
	{
		return;
	}
	
	if(r-p+1<k)
	{
		InsertionSort(a,p,r);
	}
	else
	{
		q=RandomPartition(a,p,r);
		RandomQuickSort(a,p,q-1,k);
		RandomQuickSort(a,q+1,r,k);
	}
}

int main()
{
	int i=0;
	int j=0;
	int a[BUFFER_SIZE]; 
	//隨機生成陣列 
	srand((unsigned)time(NULL));
	for(j=0;j<BUFFER_SIZE;j++)
	{
		a[j]=rand()%100;
	} 
	printf("隨機生成的陣列:\n");
	for(i=0;i<BUFFER_SIZE;i++)
	{
		printf("%d ",a[i]);
	} 
	printf("\n");
	
	RandomQuickSort(a,0,BUFFER_SIZE-1,1);
	printf("對陣列進行快速插入排序:\n"); 
	for(i=0;i<BUFFER_SIZE;i++)
	{
		printf("%d ",a[i]);
	}
	
	system("pause");
	return 0;
}