資料結構與演算法——排序演算法之快速排序
阿新 • • 發佈:2018-12-17
資料結構與演算法——排序演算法之快速排序
-
快速排序定義
快速排序由C. A. R. Hoare在1962年提出通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分別進行快速排序,整個排序過程可以遞迴進行,以此達到整個資料變成有序序列。
-
快速排序的優勢
桶排序浪費空間嚴重,而氣泡排序解決了這一問題,但是在演算法的執行效率上大打折扣。快速排序既解決了空間浪費問題,又使運算速度大幅提高,可謂一舉雙得。
-
自然語言描述(以降序為例)
- Step1: 選定一個最左或最右為基準數(本例選擇最左)
- Step2: 定義兩個標誌變數,分別指向資料的兩邊有(以下簡稱左標和右標)。
- Step3: 右標開始向左移動,直到遇到小於基準數的數時停下來。
- Step4: 左標開始向右移動,直到遇到大於基準數的數時停下來。
- Step5: 將左右兩標所指數字互換,重複第三四五步,直到左右兩標指向同一數字,這三個步驟稱為一趟。
- Step6 : 兩標指向的同一數字與基準數互換完成快排。
- Step1: 選定一個最左或最右為基準數(本例選擇最左)
- 程式碼實現:
[ 一 ] C語言實現
#include <stdio.h>
int a[101],n;//定義全域性變數,這兩個變數需要在子函式中使用
void quicksort(int left, int right);
int main()
{
int i,j;
//讀入資料
scanf("%d",&n);
for(i=1; i<=n; i++)
scanf("%d",&a[i]);
quicksort(1,n);//快速排序呼叫
//輸出排序後的結果
for(i=1; i<=n; i++)
printf("%d ",a[i]);
return 0;
}
void quicksort(int left, int right)
{
int i,j,t,temp;
if(left > right)
return;
temp = a[left];//temp中存的就是基準數
i = left;
j = right;
while(i != j)
{
//順序很重要要先從右往左找
while(a[j] >= temp && i<j)
j--;
//再從左往右找
while(a[i] <= temp && i<j)
i++;
//交換兩個數在陣列中的位置
if(i<j) //當哨兵i和哨兵j沒有相遇時
{
t = a[i];
a[i] = a[j];
a[j] =t;
}
}
//最終將基準數歸位
a[left] = a[i];
a[i] = temp;
quicksort(left,i-1);//繼續處理左邊的,這裡是一個遞迴的過程
quicksort(i+1,right);//繼續處理右邊的,這裡是一個遞迴的過程
}
- [ 二 ] java實現
public static int partition(int []array,int lo,int hi){
//固定的切分方式
int key=array[lo];
while(lo<hi){
while(array[hi]>=key&&hi>lo){//從後半部分向前掃描
hi--;
}
array[lo]=array[hi];
while(array[lo]<=key&&hi>lo){從前半部分向後掃描
lo++;
}
array[hi]=array[lo];
}
array[hi]=key;
return hi;
}
public static void sort(int[] array,int lo ,int hi){
if(lo>=hi){
return ;
}
int index=partition(array,lo,hi);
sort(array,lo,index-1);
sort(array,index+1,hi);
}
-
複雜度分析:
- 快速排序每次交換都是跳躍式的而不像冒泡每次都是相鄰交換,交換距離得到拓展,快排最壞時間複雜度為O(N^2), 與冒泡的一樣,因為快排比較與冒泡來說的優勢就是交換距離擴充套件,最差情況下優勢沒了,自然就與之一樣了。
- 快排的平均複雜度為O(NlogN)。
-
演算法思想(分而治之):
1. 古代君王統治大片國土常用分治法,如我們所知的分封制,郡縣制等等。採用分治法的原因很簡單,1. 國土面積大,2.君王自身精力有限。
2. 同樣我們面對規模較為複雜的問題時,可以藉助於將其分為等價的規模較小的幾個模組而解決,分而治之與軟體設計的模組化思想有些類似,較大問題的解決都是基於較小問題的解決藉助於遞迴而解決的。