快速排序算法

快速排序是基於分治模式的。

一.基本思路:

1.找出一個基準數;

2.重新排列數列,把比基準數小的放在前面,比基準數大的放在後面,分割結束後,基準數就是中間數,此操作也成爲分割操作;

3.遞歸的把被基準數分開的兩個序列重新排序。

快速排序是遞歸思想的經典運用。

該算法是由東尼·卡爾先生在1962年提出來的。

二.分解方法:

數組A[p…r]被劃分成兩個可能空的子數組A[p..q-1]<=A[q]<=A[q+1..r].

三.解決方法:
通過遞歸調用進行快速排序。

四.合併:

因爲兩個子數組是就地排序的,所以他們的合併不需要進行操作。

五.僞代碼:

版本一:

因爲選擇排序算法有很多種版本,此處首先選擇《算法導論》中的所用的那一版,即使用數組的最後一個元素作爲主元進行排序

QUICKSORT(A,p,r)
 If(p<r)
   Then q←PARTION(A,p,r)
              QUICKSORT(A,p,q-1)
              QUICKSORT(A,q+1,r)
 
PARTION(A,p,r)
x←A[r]
i←p-1
forj←p to r-1
   do if A[j]<=x
      then i←i+1
         exchange A[i]A[j]
exchange A[i+1]A[r]
return i+1

六.源代碼實現:

#include<stdio.h>
#include<stdlib.h>
#define MAX 8
 
void exchange(int *x,int *y)//此處必須用指針實現,否則由於函數的拷貝不能改變調用函數的參數值
{
         int temp;
         temp=*x;
         *x=*y;
         *y=temp;
}
 
int partion(int v[],int p,int r)
{
         int x=v[r];
         int i=p-1;
         int j;
         for(j=p;j<=r-1;j++)
         {
                   if(v[j]<x)
                   {
                            i++;
                            exchange(&v[i],&v[j]);
                   }
         }
         exchange(&v[i+1],&v[r]);
         return i+1;
}
void QuickSort(int v[],int p,int r)
 {
         int q=0;
         if(p<r)
         {
             q=partion(v,p,r);
             QuickSort(v,p,q-1);
             QuickSort(v,q+1,r);
         }
 
}
 
int main()
{
         int v[MAX];
         for(int i=0;i<MAX;i++)
             scanf("%d",&v[i]);
 
         QuickSort(v,0,MAX-1);
 
         for(int j=0;j<MAX;j++)
                   printf("%d\t",v[j]);
         system("pause");
         return 0;
}


七.運行結果:

wKioL1P7Ng6ii3iiAABwMgHngCY650.png

八.算法演示:

wKioL1P7NrzAtAE2AALviB5DjVs271.jpgwKiom1P7NdOjZqWQAALYCxPV-FA293.jpg

附:

版本二:

把數組的第一個元素作爲主元進行排序


僞代碼:

QUICKSORT

i←p

j←r

x←v[p]

if p<r

 while i<j

    while v[j]>=x

        j--    //從右邊向左邊數找到第一個比主元小的數

    if i<j

        v[i]=v[j] //把找到的數賦給左邊被“挖掉的”數

          i++

    while v[i]<x

          i++     //從左邊向右邊找,找到第一個比主元大的數

    if i<j

        v[j]=v[i] //再把找到的數賦給右邊“被挖掉的”數

          j--


x←v[i]

 QUICKSORT //再遞歸

 

源代碼實現:

#include<stdio.h>
#include<stdlib.h>
#define MAX 8

void QuickSort(int v[],int p,int r)
 {
	if (p<r)
	{
		int x=v[p];
		int i=p;
		int j=r;
		while(i<j)
		{
			while(v[j]>=x&&i<j)
				j--;
			if(i<j)
				v[i++]=v[j];
				

			while(i<j&&v[i]<x)
				i++;
			if(i<j)
				v[j--]=v[i];
		}
		v[i]=x;
		QuickSort(v,p,i-1);
		QuickSort(v,i+1,r);
	}
}

int main()
{
	int v[MAX];
	for(int i=0;i<MAX;i++)
		scanf("%d",&v[i]);

	QuickSort(v,0,MAX-1);

	for(int j=0;j<MAX;j++)
		printf("%d\t",v[j]);
	system("pause");
	return 0;
}

運行結果

    wKioL1P7Ng6ii3iiAABwMgHngCY650.png

算法演示:

wKiom1P74-DwFMbFAAc2tPYoOHY638.png

       從上圖可以看出最終此數列被2分爲兩個子數列,然後以此類推進行遞歸排序,請讀者自己進行後面的步驟


九.總結:


關於快速排序的版本還有很多,但無非是選擇主元的方式和位置不同罷了,這裏只選擇兩個典型的方法進行初步介紹,至於算法性能等進階的問題,會在後面繼續進行詳細介紹。


版本一和版本二,理解任意一種即可,但個人認爲第二種似乎比較容易理解,且代碼也簡潔明瞭,值得學習。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章