經典排序演算法 快速排序(Quick Sort)

2021-07-24 12:19:41 字數 3217 閱讀 2153

快速排序演算法被稱為20世紀十大演算法之一,是最重要的演算法之一,是一定要掌握和熟練的!

快速排序的基本思想是:(分治法)

1.先從數列中取出乙個數作為基準數。

2.分割槽過程,將比這個數大的數全放到它的右邊,小於或等於它的數全放到它的左邊。

3.再對左右區間重複第二步,直到各區間只有乙個數。

假如現在我們要對這個序列,進行快速排序,序列的原始狀態是這樣的:

//算出中間值關鍵** 

intpartition(sqlist *l, int low, int high)

swap(l, low, high);

while(lowr[low] <= pivotkey)

swap(l, low, high);

}return low;

}//對無序序列進行排序

void qsort(sqlist *l, int low, int high)

}

方法qsort表現了我們的演算法思想,首先通過partition算出中間值,然後再對兩邊的值進行遞迴排序。

partition方法,初始時pivotkey 為50,然後進行邏輯判斷。

當high指標所指向的值大於pivotkey,則一直讓high指標遞減,直到high指向乙個比pivotkey小的數時,然後讓high指標和low指標的值交換,目的就是為了把較小的值移到左邊。圖中20會與50交換。

當low指標指向的值小於pivotkey時,則一直讓low遞增,直到low指向乙個比pivotkey大的數時,然後讓high指標和low指標的值交換,目的就是為了把較大的值移到右邊。圖中low指標會移到90,然後90和50交換。

#include 

#include

#define maxsize 10

typedef

struct

sqlist;

void swap(sqlist *l, int i, int j)

void initsort(sqlist *l) ;

for(int i = 1; ir[i] = a[i-1];

}}//算出中間值關鍵**

int partition(sqlist *l, int low, int high)

swap(l, low, high);

while(lowr[low] <= pivotkey)

swap(l, low, high);

}return low;

}//對無序序列進行排序

void qsort(sqlist *l, int low, int high)

}void quicksort(sqlist *l)

void searchsort(sqlist *l)

}int main()

結果如下:

在最好的情況下,第一次partition會掃瞄n個關鍵字,做n次比較,因此此時的時間複雜度為n,記為t(n)。然後,獲得的中間值將陣列一分為二,那麼各自需要t(n/2),此時的總時間為:2 t(n/2)+n

如下:

t(n) <= 2t(n / 2) + n

t(n) <= 2(2t(n / 4) + n/2) + n = 4t(n/4) + 2n

t(n) <= 4(2t(n / 8) + n/4) + 2n = 8t(n/8) + 3n

…. t(n) <= nt(1) + (logn) * n = o(nlogn)

所以,最優情況下,快速排序的演算法時間複雜度為o(nlogn)

1、 發現乙個問題,partition函式中,中間值pivotkey的取值是乙個很值得商榷的問題,我們一開始設它為l->r[low],只是剛好l->r[low]為50,因此pivotkey的值是比較接近中間值的。但是假如在有這樣乙個序列,,那麼此時pivotkey的值為9,但是9是整個序列最大值,這樣我們的無用比較會做多少次啊!

我們可以用三數取中法,取三個關鍵字排序,再將中間值作為序列的中間值,一般取左端,中間,右端三個數。

//算出中間值關鍵** 

intpartition(sqlist *l, int low, int high)

if(l->r[m] > l->r[high])

if(l->r[m] > l->r[low])

pivotkey = l->r[low];

while(low < high)

swap(l, low, high);

while(lowr[low] <= pivotkey)

swap(l, low, high);

}return low;

}

2、pivotekey的交換次數不必要,因為他最終都會到達中間(low

public

static

int partition(int low, int high)

//直到發現了有半部分有小於privotekey的數

//採用替換

array[low] = array[high];

while(lowarray[low] <= privotekey)

array[high] = array[low];

}array[low] = back;

return low;

}

3、快排和插入排序結合使用

當陣列非常小的時候,使用快速排序反而有些大材小用了,因此遞迴其實也會影響效能的,所以我們可以定義乙個閥值,當陣列長度低於這個閥值時,就選擇插入排序

經驗表明,最好的組合方式是當n(子陣列的長度)小於等於16時就使用插入排序

//對無序序列進行排序 

void qsort(sqlist *l, int low, int high) else

}

《經典排序演算法 快速排序》

快速排序是實踐中已知的最快的排序演算法,平均執行時間o nlogn 該演算法之所以快是因為非常精煉和高度優化的內部迴圈。它也是一種分治的遞迴演算法,將陣列s排序的基本演算法由下列簡單的四步組成 如果s中元素個數是0或1,則返回。取s中任一元素v,稱之為樞紐元。將s 分成兩個不相交的集合s1 x v ...

經典排序演算法 快速排序

使用分割槽演算法並找出主元 對主元兩邊的序列分別進行排序 整體時間複雜度 o nlog n public class quicksort 分割槽演算法 public static intpartition int a,int l,int r else if a l a mid a l a r els...

經典演算法 快速排序

題目說明 快速排序是由東尼 霍爾所發展的一種排序演算法。在平均狀況下,排序n 個專案要 n log n 次比較。在最壞狀況下則需要 n2 次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他 n log n 演算法更快,因為它的內部迴圈 inner loop 可以在大部分的架構上很有效率地被實...