快速排序演算法被稱為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 可以在大部分的架構上很有效率地被實...