三向切分快速排序
我們知道快速排序的應用非常廣泛,也許你可以非常熟練的可以寫出一個快速排序,在大多數情況下快速排序是可以適用的,但是快速排序還有一個改進的算法稱為三向切分快速排序,它是快速排序的一個變種,尤其適合在數據大量重復的情況下使用,它對快速排序性能的提升程度取決于重復數字的多少,平均時間復雜度介于N和NlogN之間。
在學習三向切分快速排序之前,我們先來了解一下 E.W.Dijlstra(Dijkstra最短路徑算法的發明者)曾經提出的一個關于荷蘭國旗的問題:
荷蘭國旗包含三種顏色:紅、白、藍。有這三種顏色的球,算法的目標是將這三種球按荷蘭國旗顏色順序正確地排列,即紅白藍的順序排序。
這里我們使用0,1,2來表示紅、白、藍。要求時間復雜度為O(n);
例如:
解決方法如下:
public void sortColors(int[] nums) {int zero = -1, one = 0, two = nums.length;while (one < two) {if (nums[one] == 0) {swap(nums, ++zero, one++);} else if (nums[one] == 2) {swap(nums, --two, one);} else {++one;}} }private void swap(int[] nums, int i, int j) {int t = nums[i];nums[i] = nums[j];nums[j] = t; }可以看到它使用了三個指針,分別代表三個不同的顏色。one指向未知的顏色,之后判斷,如果是紅色則和zero交換,如果是藍色則和two交換。最后數組中的情況如下:
其實三向切分快速排序基本上也是這個思想,如下:
對比上面就是<V為紅色,=V為白色,>V為藍色。轉換為代碼就是:
最后,在編寫三向切分快速排序的時候要尤其注意數組下標的正確與否,這里的下標寫法,我們使用的是上面解決荷蘭國旗的下標寫法。
總結
- 上一篇: 使用Fork/Join框架优化归并排序
- 下一篇: 一个简单的因数分解java代码