排序算法之快速排序(C語言)

一、原理講解

快速排序的核心思想是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。

簡單的說法,就是設置一個基準,將無序數組的數據分隔成兩部分,基準左邊的數據都小於基準,基準右邊的數據都大於基準。然後不斷設置基準與參與排序的數據個數進行排序,直至整個數組爲一個有序數組。

假定有一個無序整型數組:int arr4[10] = {11, 7, 0, 1, 5, 8, 10, 31, 2, 19};

下面詳細講解快速排序的實現過程:

第一步,選取第數組第一個元素作爲基準並且將值保存到par變量中,圖中紅框的元素。設置參與排序的數組下標start和end。

第二步,取end對應的元素與par進行比較,若 arr[end] < par ,則給start對應的元素賦值arr[end](arr[start] = arr[end]), 否則end--(end前移)。其中arr[end] > par 所以, end--,end前移。得到如下結果:

此時繼續取end對應的元素與par進行比較,arr[end] < par ,所以給arr[start]賦值arr[end],(arr[start] = arr[end])。得到如下結果:

此時取start對應的元素與par進行比較,若arr[start] > par,則給arr[end]賦值arr[start],(arr[end] = arr[start]),否則start++,將start後移。

這裏start = 0時,arr[start]沒有小於par,所以將start後移,當start = 2時,arr[start]沒有小於par,所以將start後移....

當start = 7時,arr[start] > par,所以arr[end] = arr[start]。結果如下:

此時切換回取end對應的數據進行比較。

此時我們將end前移之後,我們發現start = end。這會第一次排序完成,我們將arr[start] 賦值par,(arr[start] = par)。

得到的結果如下:

這裏我們能清晰的看到一開始選定的基準點11,他左邊的數據都小於11,右邊的數據都大於11。

後面我們將循環以上步驟,直至整個數組爲有序數組爲止(start >= end),注意每輪排序都需要重新設置參與排序的數組元素起始位置和結束位置。直至整個所有參與排序的子數組都滿足(start >= end)後結束排序。

這裏我們得到結論:

1.先從隊尾開始向前掃描且當start < end時,如果arr[end] > par,則end--(end前移),但如果arr[end] < par,則將end的對應元素的值賦值給arr[start],即arr[start] = arr[end],同時要轉換數組掃描的方式,即需要從隊首開始向隊尾進行掃描了。
  2.同理,當從隊首開始向隊尾進行掃描時,如果arr[start] < par,則start++(start後移),但如果arr[start] > par了,則就需要將start對應元素的值賦值給end對應的元素,即arr[start] = arr[end],同時將數組掃描方式換爲由隊尾向隊首進行掃描。
  3.不斷重複1和2,指導start >= end時(其實是start = end),start或end的位置就是該基準數據在數組中的正確索引位置。

這裏有一點我們需要注意,每次排序完,進行第二次排序時,排序的數據個數只是基準左邊或者右邊的數據。如上個例子,第一輪排序完之後進行第二次排序,我們進行排序的數組元素就只有arr[0]到arr[6],因爲arr[0]到arr[6]的數據都小於基準值,直至參與排序的左邊數組對應的star = end。

然後我們開始排序基準右邊的數組。排序步驟與上相同。

如下圖是該數組每輪排序後的結果:

 

二、具體代碼

/*
函數名:int QuickSort(int data[], int start, int end);
函數功能:使用快速排序的方法,將數組按從小到大排序
函數參數:
         data[]:數組首地址
         start:數組首個元素下標
         end:數組最後一個元素下標
		
函數返回值:
           函數成功排序數組返回0,失敗返回-1
*/

int QuickSort(int data[], int start, int end)
{
	
	int i = start;                      
	int j = end;
	int par = data[start];               //選定基準
	
	if (start >= end)                    //當start >= end 結束該輪循環
		return -1;

	while (i < j)
	{
        //在i < j 的前提下,找到par > data[j] 的數據,然後就將data[j]的值賦給data[i]
		while (i < j && par <= data[j])     //此處若是 par < data[j]  遇到兩個相同的數則會排序失敗
			j--;
		
			data[i] = data[j];
		
        //在i < j 的前提下,找到par < data[i] 的數據,然後就將data[i]的值賦給data[j]
		while (i < j && par >= data[i])    //此處若是 par > data[i]  遇到兩個相同的數則會排序失敗
			i++;
		
			data[j] = data[i];
	
	}
	
	
	data[i] = par;                  //將基準值存放到對應的位置
	QuickSort(data, start, i - 1);  //遞歸排序左子數組  並且更改參與排序的數組元素
	QuickSort(data, i + 1, end);    //遞歸排序右子數組  並且更改參與排序的數組元素
	
	return 0;
}

這裏程序使用的遞歸調用,若對遞歸不熟練的話,讀者可以查詢一下,使用棧實現快速排序的代碼,所有的遞歸函數都可以使用棧實現。

 

倉促成文,不當之處,尚祈方家和讀者批評指正。聯繫郵箱[email protected]


 

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