演算法手記(7)快速排序

2022-01-20 12:54:52 字數 2429 閱讀 6033

終於到了經典的快排了,作為20世紀科學和工程領域十大演算法之一,自60年代發明以來,一直吸引著一批批工程師和科學家對其改進,今天我們就分析快排演算法以及它的幾種改進方案。

快速排序

概述:快速排序演算法也是基於分治思想的方案,與歸併排序不同的是,它是原地排序,同時可以將長度為n的陣列排序所需的時間和nlogn成正比,我們已經學習過的演算法都無法將這兩個優點結合起來。

快速排序流行的原因是因為它實現簡單,適用於各種不同的輸入資料且在一般應用中比其他演算法要快得多,他可能是使用最廣泛的演算法了。

分析:快排是一種分治的排序演算法。它講乙個陣列分成兩個子陣列,將兩部分獨立地排序,當兩個子陣列都有序時整個陣列自然就有序啦。在快速排序中,切分(partition)的位置取決於陣列的內容,該演算法的關鍵也在於切分,這個過程需要滿足3個條件:

1.對於某個j,a[j]已經排定;

2.a[lo]到a[j-1]中的所有元素都不大於a[j];

3.a[j+1]到a[hi]中的所有元素都不小於a[j];

根據歸納法不難證明他能正確的排序陣列:如果左子陣列和右子陣列都是有序的,那麼左子陣列,切分元素,右子陣列組成的結果陣列也一定是有序的。它是乙個隨機化演算法,因為它在排序之前順序會被打亂,這麼做是希望可以**該演算法的效能特徵。

這裡切分的一般策略是先隨意地取a[lo]為切分元素,然後我們分別自左向右掃瞄直到找到乙個大於等於它的元素,再自右向左掃瞄直到找到乙個小於等於它的元素,我們交換這兩個元素的位置。如此繼續,就可以保證坐指標i的元素不大於切分元素,右指標j的元素不小於切分元素,最後當i和j相遇時,將a[lo]與a[j]交換,然後返回j即可。

實現:

public

class

quick

private

static

void sort(icomparable a, int lo, int

hi)

private

static

int partition(icomparable a, int lo, int

hi)

exch(a, lo, j);

return

j; }

private

static

bool

less(icomparable i, icomparable j)

private

static

void exch(icomparable a,int i, int

j)

public

static

void test(int

size)

;console.writeline(data[i]);

}console.writeline(

"after sort:");

quick.sort(data);

for (int i = 0; i < size; i++)

stopwatch.elapsedtime();

}public

static

void main(string

args)

}

注意點:

1.原地切分

如果使用輔助陣列,則可以很輕鬆的實現切分,但是將切分後的陣列複製回去的開銷可能是我們無法承受的,這會大大降低演算法的排序速度。

2.別越界

如果切分元素是陣列中最小或最大的元素,我們就需要確保掃瞄陣列別跑出邊界,需要實現明確地檢測來防止這種情況。

3.保持隨機性

陣列元素順序是被打亂過的,它的所有子陣列也都是隨機排序的,這對**演算法的執行時間很重要,同時也能減小最壞情況發生機率。

4.終止迴圈

有經驗的程式設計師都明白終止迴圈需要格外小心,快速排序的切分迴圈也不例外。乙個常見的錯誤是沒有考慮到陣列中可能包含和切分元素的值相同的其他元素。

5.處理切分值有重複的情況

這裡的實現演算法裡,左側掃瞄最好在遇到大於等於切分值時停下,右側掃瞄在遇到小於等於切分值停下。儘管這樣可能將一些等值的元素交換,但在某些典型應用中,這可以避免演算法的執行時間變為平方級別。

6.終止遞迴

有經驗的程式設計師在保證遞迴總是能夠結束也是需要小心的。快速排序的乙個常見錯誤就是不能保證將切分元素放入正確的位置,從而導致程式在切分元素正好是最大或最小值時陷入了無限的遞迴之中。

總結:數學上對快速排序已經有了詳盡的分析,因此我們能夠精確說明它的效能。快速排序切分方法的內迴圈會用乙個遞增的索引將陣列元素和乙個定值比較,很難想象排序演算法中還有比這個更短小的內迴圈了。

快速排序的另乙個優勢在於它的比較次數較少,快速排序最好的情況是每次都能正好將陣列對半分,這種情況下正好滿足分治遞迴的cn=2cn/2+n公式,即cn~nlogn。

儘管快速排序有很多優點,但它的基本實現有乙個潛在的缺點:在切分不平衡時會極為低效。我們在快排之前將陣列隨機打亂就是為了防止此種情況,這樣可以將糟糕的切分情況可能性降到最低。

演算法手記之快速冪

快速冪是一種快速求出 ab 的值的演算法,複雜度為o logn 而一般的樸素演算法是由乙個for迴圈慢慢算,算完需要o n 的時間,這顯然不符合yxh老師高山流水般的思路,所以我們需要乙個高效的演算法來解決這個問題。快速冪的原理 假設要求211的值,指數11可以使用二進位制的形式寫成11 20 21...

7 快速排序

快速排序 快速排序是在實際中最常用的一種排序演算法,速度快,效率高。就像名字一樣,快速排序是最優秀的一種排序演算法。思想 快速排序採用的思想是分治思想。portition 快速排序是找出乙個元素 理論上可以隨便找乙個 作為基準 pivot 然後對陣列進行分割槽操作,使基準左邊元素的值都不大於基準值,...

演算法手記(5)初級排序演算法

排序是將一組物件按照一定的規則重新排列的過程。即使目前完全可以使用標準庫中的排序函式,學習排序演算法仍然有著較大意義 排序演算法的學習可以幫助你全面了解比較演算法效能的方法 類似的技術上能有效解決其他型別的問題 排序演算法通常是我們解決問題的第一步 更重要的是這些演算法都很經典,優雅和高效。排序在商...