詳解快速排序演算法中的區間劃分法及Java實現樣本_java

來源:互聯網
上載者:User

快速排序是C.R.A.Hoare於1962年提出的一種劃分交換排序。該方法的基本思想是:
1.先從數列中取出一個數作為基準數。
2.分區過程,將比這個數大的數全放到它的右邊,小於或等於它的數全放到它的左邊。
3.再對左右區間重複第二步,直到各區間只有一個數。
演算法的思路很清晰,但是如果在區間劃分過程中邊界值沒有處理好,也是很容易出現bug的。下面給出兩種比較清晰的思維來指導區間劃分代碼的編寫。
第一種思維即所謂的挖坑法思維,下面通過分析一個執行個體來分析一下挖坑法的過程:
以一個數組作為樣本,取區間第一個數為基準數。

初始時,left = 0; right= 9;   X = a[left] = 72
由於已經將a[0]中的數儲存到X中,可以理解成在數組a[0]上挖了個坑,可以將其它資料填充到這來。
從right開始向前找一個<=X的數。顯然,right=8時,符合條件,將a[8]挖出再填到上一個坑a[left]中。 這樣一個坑a[0]就被搞定了,但又形成了一個新坑a[8],這怎麼辦了?簡單,再找數字來填a[8]這個坑。這次從left開始向後找一個大於X的數,當left=3,符合條件,將a[3]挖出再填到上一個坑a[right] 中;
數組變為:


再重複上面的步驟,最終數組將變成如下形式:

可以看出a[5]前面的數字都小於它,a[5]後面的數字都大於它。將X填入a[5]的坑中,資料變為:

因此再對a[0…4]和a[6…9]這二個子區間重複上述步驟就可以了。
對挖坑填數進行總結
1.i =L; j = R; 將基準數挖出形成第一個坑a[i]。
2.j--由後向前找比它小的數,找到後挖出此數填前一個坑a[i]中。
3.i++由前向後找比它大的數,找到後也挖出此數填到前一個坑a[j]中。
4.再重複執行2,3二步,直到i==j,將基準數填入a[i]中。
照此分區方法,快速排序Java代碼如下:

public class Partition {   /**   * 基於base劃分,小的在左,大的在右, 不要求整個序列有序   *   * @param ary   * @param base   */  static void sort(int[] ary, int base) {   int left = 0;   int right = ary.length - 1;      int leftpoint = left, rightpoint = right;      while (true) {    // 分成左右兩邊同時進行比較,一邊從左向右,一邊從右向左,    while (leftpoint < right && ary[leftpoint++] < base); //leftpoint大於right或ary[leftpoint]>base停止迴圈        while (rightpoint >= left && ary[rightpoint--] > base); //反之    System.out.println("左邊需要交換的索引:" + (leftpoint-1));    System.out.println("右邊需要交換的索引:"+ (rightpoint+1));    //上面拿到了不合格兩個索引,即需要交換的兩個索引    if (leftpoint - 1 < rightpoint + 1) {//需要交換     swap(ary, leftpoint - 1, rightpoint + 1);     Util.printArray(ary);     leftpoint = left;     rightpoint = right;    } else {     break;    }   }  }     private static void swap(int[] ary, int a, int b) {   int temp = ary[a];   ary[a] = ary[b];   ary[b] = temp;  }   public static void main(String[] args) {   int[] ary = Util.generateIntArray(10);   System.out.println("原序列:");   Util.printArray(ary);   sort(ary, 5);   System.out.println("排序後:");   Util.printArray(ary);  } } 

結果:

原序列: [2, 8, 4, 3, 7, 5, 1, 9, 0, 6] 左邊需要交換的索引:1 右邊需要交換的索引:8 [2, 0, 4, 3, 7, 5, 1, 9, 8, 6] 左邊需要交換的索引:4 右邊需要交換的索引:6 [2, 0, 4, 3, 1, 5, 7, 9, 8, 6] 左邊需要交換的索引:5 右邊需要交換的索引:5 排序後: [2, 0, 4, 3, 1, 5, 7, 9, 8, 6] 

區間劃分的的另一種指導思維:
將數組的第一個元素作為區間劃分值,從第二個元素開始分區,直到形成如圖所示的結果,

然後交換l<t區間的右邊界值和t,形成如下的結果:

如此,可以如下編寫快速排序代碼:

public void qSort(int array[],int left,int right)  {   if(left < right){     int key = array[left];     int high = right;        int low = left+1;        while(true){          while(low <= high && array[low] <= key) low++;      while(low <= high && array[high] >= key) high--;             if(low > high)      break;      swap(array,low,high);    }    swap(array,left,high);        printArray(array);     qSort(array,left,high-1);     qSort(array,high+1,right);   }  } 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.