分治法在排序算法中的应用(JAVA)--快速排序(Lomuto划分、Hoare划分、随机化快排)
分治法在排序算法中的應用--快速排序
時間復雜度:平均O(nlogn),最壞O(n^2)
如果說歸并排序是按照元素在數組中的位置劃分的話,那么快速排序就是按照元素的值進行劃分。劃分方法由兩種,本節將主要介紹Huare劃分,這也是我們通常采用的劃分方法。
為了文章完整,下面只給出基于Lomuto劃分的代碼,詳細分析請參考減治法在查找算法中的應用(JAVA)--快速查找。
1、基于Lomuto劃分的快速排序算法
public class Main {static int[] a= {5, 3, 1, 9, 8, 2, 4, 7};public static void main(String[] args) {fastsort(0, a.length-1);for (int i = 0; i < a.length; i++) {System.out.print(a[i] + " ");}}private static int Lomuto(int l, int r) {int p = a[l];int s = l;for (int i = l+1; i <= r; i++) {if (a[i] < p) {s = s+1;int temp = a[s];a[s] = a[i];a[i] = temp;}}int temp = a[l];a[l] = a[s];a[s] = temp;return s;}private static void fastsort(int l, int r) {if (l < r) {int s = Lomuto(l, r);fastsort(l, s-1);fastsort(s+1, r);}} }2、基于Hoare劃分的快速排序算法
Hoare劃分是一種更為復雜的劃分方式,但是這也是在網上最為流行的一個劃分方式。
我們假設有一個數組a[0, n-1],其子數組為a[l, r](0 <= l <= r <= n-1),假定首個元素為樞軸p,下面從數組兩端進行掃描,并將掃描到的元素與樞軸比較。從左到右掃描(用指針i來表示),掃描到第一個大于等于樞軸p的,停止;從右到左掃描(用指針j表示,遇到第一個小于等于樞軸的元素)。這里注意等于樞軸的元素也要進行處理,這樣可以保證數組分的更加平均。如果遇到相等元素繼續掃描,對于一個具有n個相同元素的數組來說,劃分后得到的兩個子數組長度可能為n-1和0。
兩側的掃描都停止之后,根據掃描指針是否相交會有三種情況:若 i < j,則交換a[i]與a[j],i+1,j-1;若 i > j,交換a[p]與a[j];若i = j,則交換a[p]與a[j]。眼尖的讀者估計看出來了,后兩種情況其實是一種。
下圖為Hoare劃分的示意圖:
public class Main {static int[] a= {5, 3, 1, 9, 8, 2, 4, 7};public static void main(String[] args) {fastsort(0, a.length-1);for (int i = 0; i < a.length; i++) {System.out.print(a[i] + " ");}}private static int Hoare(int l, int r) {int p = a[l];int i = l-1;int j = r+1 ;while (true) {do {j--;} while (a[j] > p);do {i++;} while (a[i] < p);if (i < j) {int temp = a[i];a[i] = a[j];a[j] = temp;} elsereturn j;}}private static void fastsort(int l, int r) {if (l < r) {int s = Hoare(l, r);fastsort(l, s);fastsort(s+1, r);}} }?
?
一般來說,如果我們要考慮一個算法的實用性,我們需要討論的不是最壞情況下的效率,而應該是平均情況下的效率。實際經過分析,快速排序平均情況下的操作僅比最優情況多執行39%的比較過程而已。所以在處理隨機序列時,速度要強于歸并排序和堆排序。
缺點:快速排序并非穩定性排序方式,空間復雜度為O(logn),不及堆排序的空間復雜度O(1).
提出問題:對于數組非常小的情況下(對于大多數計算機來說,元素個數為5-15),使用插入排序會更快
解決思路1:判斷元素個數,較小時采用插入排序,較大時采用快速排序。
解決思路2:不再對劃分出來的較小數組排序,而是在快速排序結束后再使用插入排序的方法對整個接近有序的數組進行細微調節。
?
隨機化快排:使用隨機元素作為樞軸
提出問題:如果我們每次都選取第一個元素為樞軸,這自然會有諸多不便,不能應對一些特殊的情況。
解決思路:隨機化快速排序、三平均劃分法,下面給出代碼,基本思想還是劃分,有興趣的讀者可以研究一下。
public class Main {static int[] a= {5, 3, 1, 9, 8, 2, 4, 7};public static void main(String[] args) {fastsort(0, a.length-1);for (int i = 0; i < a.length; i++) {System.out.print(a[i] + " ");}}private static int random_partition(int l, int r) {int i = (int) (l + Math.random() % (r - l + 1));int temp = a[i];a[i] = a[r];a[r] = temp;return partition(l, r);}private static int partition(int l, int r) {int p = a[r];int i = l - 1;for (int j = l; j < r; j++) {if (a[j] <= p) {i++;int temp = a[i];a[i] = a[j];a[j] = temp;}}int temp = a[i+1];a[i+1] = a[r];a[r] = temp;return i+1;}private static void fastsort(int l, int r) {if (l < r) {int s = random_partition(l, r);random_partition(l, s-1);random_partition(s+1, r);}} }三平均劃分法快排:以最左元素、最右元素、最中間元素的中位數為樞軸
public class Main {static int[] a= {5, 3, 1, 9, 8, 2, 4, 7};public static void main(String[] args) {fastsort(0, a.length-1);for (int i = 0; i < a.length; i++) {System.out.print(a[i] + " ");}}public static int mid_partition(int l, int r){int range = r - l + 1;int mid1 = (int) (l + Math.random() % range);int mid2 = (int) (l + Math.random() % range);int mid3 = (int) (l + Math.random() % range);int mid = (a[mid1] < a[mid2]) ?(a[mid2] < a[mid3] ? mid2 : (a[mid1] < a[mid3] ? mid3 : mid1)):(a[mid1] < a[mid3] ? mid1 : (a[mid2] < a[mid3] ? mid2 : mid3));int temp = a[mid];a[mid] = a[r];a[r] = temp;return partition(l, r);}private static int partition(int l, int r) {int p = a[r];int i = l - 1;for (int j = l; j < r; j++) {if (a[j] <= p) {i++;int temp = a[i];a[i] = a[j];a[j] = temp;}}int temp = a[i+1];a[i+1] = a[r];a[r] = temp;return i+1;}private static void fastsort(int l, int r) {if (l < r) {int s = mid_partition(l, r);fastsort(l, s-1);fastsort(s+1, r);}} }提出問題:在劃分方式上Lomuto劃分和Hoare劃分也可以進行改進,使用諸如三路劃分的方式,將數組劃分3段,每段元素分別小于、等于、大于樞軸元素等等。當然,這些就僅供研究學習了,平時我們使用最簡單版本的快速排序是沒有任何問題的。
總結
以上是生活随笔為你收集整理的分治法在排序算法中的应用(JAVA)--快速排序(Lomuto划分、Hoare划分、随机化快排)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: F5刷新表单页不能清空缓存
- 下一篇: 解决echart中:Cannot rea