java演算法實踐之快速排序

2021-06-29 02:16:14 字數 1817 閱讀 1888

快速排序是乙個知名度極高的排序演算法,其對於大資料的優秀排序效能和相同複雜度演算法中相對簡單的實現使它注定得到比其他演算法更多的寵愛。

演算法概述/思路

快速排序一般基於遞迴實現。其思路是這樣的:

1.選定乙個合適的值(理想情況中值最好,但實現中一般使用陣列第乙個值),稱為「樞軸」(pivot)。

2.基於這個值,將陣列分為兩部分,較小的分在左邊,較大的分在右邊。

3.可以肯定,如此一輪下來,這個樞軸的位置一定在最終位置上。

4.對兩個子陣列分別重複上述過程,直到每個陣列只有乙個元素。

5.排序完成。

public

static

void

main(string args) ;

quicksort(arr,0,arr.length-1);

printarr(arr);

}public

static

void

quicksort(int arr,int low,int high)

}public

static

intpartitaion(int arr,int low, int high)

public

static

void

printarr(int arr)

}

演算法效能/複雜度

可以看出,每一次呼叫partition()方法都需要掃瞄一遍陣列長度(注意,在遞迴的時候這個長度並不是原陣列的長度n,而是被分隔出來的小陣列,即n*(2^(-i))),其中i為呼叫深度。而在這一層同樣長度的陣列有2^i個。那麼,每層排序大約需要o(n)複雜度。而乙個長度為n的陣列,呼叫深度最多為log(n)層。二者相乘,得到快速排序的平均複雜度為o(n ㏒n)。

通常,快速排序被認為是在所有同數量級的排序方法中,平均效能最好。

從**中可以很容易地看出,快速排序單個棧的空間複雜度不高,每次呼叫partition方法時,其額外開銷只有o(1)。所以,最好情形下快速排序空間複雜度大約為o(㏒n)。

演算法優化

上面這個快速排序演算法可以說是最基本的快速排序,因為它並沒有考慮任何輸入資料。但是,我們很容易發現這個演算法的缺陷:這就是在我們輸入資料基本有序甚至完全有序的時候,這演算法退化為氣泡排序,不再是o(n㏒n),而是o(n^2)了。

究其根源,在於我們的**實現中,每次只從陣列第乙個開始取。如果我們採用「三者取中」,即arr[low],arr[high],arr[(low+high)/2]三者的中值作為樞軸記錄,則可以大大提高快速排序在最壞情況下的效能。但是,我們仍然無法將它在陣列有序情形下的效能提高到o(n)。還有一些方法可以不同程度地提高快速排序在最壞情況下的時間效能。

此外,快速排序需要乙個遞迴棧,通常情況下這個棧不會很深,為log(n)級別。但是,如果每次劃分的兩個陣列長度嚴重失衡,則為最壞情況,棧的深度將增加到o(n)。此時,由棧空間帶來的空間複雜度不可忽略。如果加上額外變數的開銷,這裡甚至可能達到恐怖的o(n^2)空間複雜度。所以,快速排序的最差空間複雜度不是乙個定值,甚至可能不在乙個級別。

為了解決這個問題,我們可以在每次劃分後比較兩端的長度,並先對短的序列進行排序(目的是先結束這些棧以釋放空間),可以將最大深度降回到o(㏒n)級別。

演算法穩定性

快速排序並不是穩定的。這是因為我們無法保證相等的資料按順序被掃瞄到和按順序存放。

演算法適用場景

快速排序在大多數情況下都是適用的,尤其在資料量大的時候效能優越性更加明顯。但是在必要的時候,需要考慮下優化以提高其在最壞情況下的效能。

Java排序演算法之快速排序

首先在陣列中選擇乙個基準點 該基準點的選取可能影響快速排序的效率,後面講解選取的方法 然後分別從陣列的兩端掃瞄陣列,設兩個指示標誌 lo指向起始位置,hi指向末尾 首先從後半部分開始,如果發現有元素比該基準點的值小,就交換lo和hi位置的值,然後從前半部分開始掃秒,發現有元素大於基準點的值,就交換l...

Java排序演算法之快速排序

基本思想 在資料序列中選擇乙個值作為比較的基準值,每趟從資料序列的兩端開始交替進行,將小於基準值的元素交換到序列前端,將大於基準值的元素交換到序列後端,介於兩者之間的位置則成為基準值的最終位置,直到子串行長度為1,完成排序 以序列,進行快速排序,以下是一趟快速排序過程示意圖 private stat...

Java排序演算法之快速排序

快速排序是將分治法運用到排序問題中的乙個典型例子,快速排序的基本思想是 通過 乙個樞軸 pivot 元素將 n 個元素的序列分為左 右兩個子串行 ll 和 lr,其中子串行 ll中的元素均比樞軸元素小,而子串行 lr 中的元素均比樞軸元素大,然後對左 右子串行分別進行快速排序,在將左 右子串行排好序...