Java演算法-快速排序

來源:互聯網
上載者:User

標籤:

  快速排序也是用歸併方法實現的一個“分而治之”的排序演算法,它的魅力之處在於它能在每次partition(排序演算法的核心所在)都能為一個數組元素確定其排序最終正確位置(一次就定位準,下次迴圈就不考慮這個元素了)。

 

  快速排序的partition操作按以下邏輯進行,假定本次排序的數組為arr:

1) 選擇一個元素(為了簡單起見,就選擇本次partition的第一個元素,即arr[0])作為基準元素,接下來的步驟會為其確定排序完成後最終的位置;

2) 1)  接下來需要遍曆[1…n-1]對應的數組元素以協助找到arr[0]值(以v替代)對應的位置,定義i為當前訪問數組的索引,lt為值小於v的最大索引,gt為值大於v的最小索引,那麼在遍曆過程中,如果發現i指向的值與v相等,則將i值加1,繼續下一次比較;如果i指向的值比v小,則將i和lt對應的元素進行交換,然後分別將兩個索引加1;如果i指向的值比v大,則將i與gt對應的元素進行交換,然後i自增,gt自減。迴圈遍曆完成(i > gt時結束)之後可以保證[0…lt-1]對應的值都是比v小的,[lt..gt]之間的值都是與v相等的,[gt+1…n-1]對應的值都是比v大的。

3) 分別對[0…lt-1]和[gt+1…n-1]兩個子數組進行排序,如此遞迴,直至子子子數組的長度為0。

 

  下面舉個partition的具體執行個體:

初始(i = 1, lt = 0, gt = 8):       [41, 59, 43, 26, 63, 30, 29, 26, 42](需要確定位置的為0th[41])第一趟(i = 1, lt = 0, gt = 8):       [41, 42, 43, 26, 63, 30, 29, 26, 59](1st[59] > 41,1st[59]<->8th[42],gt--)第二趟(i = 1, lt = 0, gt = 7):       [41, 26, 43, 26, 63, 30, 29, 42, 59](1st[42] > 41,1st[42]<->7th[26],gt--)第三趟(i = 1, lt = 0, gt = 6):       [26, 41, 43, 26, 63, 30, 29, 42, 59](1st[26] < 41, 1st[26]<->0st[41],i++, lt++)第四趟(i = 2, lt = 1, gt = 6):       [26, 41, 29, 26, 63, 30, 43, 42, 59](2nd[43] > 41,2nd[43]<->6th[29],gt--)第五趟(i = 2, lt = 1, gt = 5):       [26, 29, 41, 26, 63, 30, 43, 42, 59](2nd[29] < 41, 2nd[29]<->1st[41],i++,lt++)第六趟(i = 3, lt = 2, gt = 5):           [26, 29, 26, 41, 63, 30, 43, 42, 59](3rd[26] < 41,3rd[26]<->2nd[41],i++,lt++)第七趟(i = 4, lt = 3, gt = 5):       [26, 29, 26, 41, 30, 63, 43, 42, 59] (4th[63] > 41,4th[63]<->5th[30],gt--)第八趟(i = 4, lt = 3, gt = 4):           [26, 29, 26, 30, 41, 63, 43, 42, 59](4th[30] < 41,4th[30]<->3rd[41],i++,lt++)

 

 

可以看出,在一次partition之後,以41為分割線,41左側皆為比它小的元素,41右側皆為比它大或相等的元素(當然這個執行個體比較特殊,沒有出現和41相等的元素)。快速排序顧名思義就是排序速度非常快,後面我會放在我機器上跑各個排序方法的時間對比圖。值得一提的是JDK中在Arrays工具內中內建的sort方法就是接合插入排序和三路快速排序實現的,有興趣的同學可以看看JDK的源碼。

 

快速排序使用分治法策略來把一個序列分為兩個子序列。

把整個序列看做一個數組,把第零個位置看做中軸,和最後一個比,如果比它小交換,比它大不做任何處理;交換了以後再和小的那端比,比它小不交換,比他大交換。這樣迴圈往複,一趟排序完成,左邊就是比中軸小的,右邊就是比中軸大的,然後再用分治法,分別對這兩個獨立的數組進行排序。

 

實現代碼:

/**   * 快速排序<br/>   * <ul>   * <li>從數列中挑出一個元素,稱為“基準”</li>   * <li>重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分割之後,   * 該基準是它的最後位置。這個稱為分割(partition)操作。</li>   * <li>遞迴地把小於基準值元素的子數列和大於基準值元素的子數列排序。</li>   * </ul>   *    * @param numbers   * @param start   * @param end   */  public static void quickSort(int[] numbers, int start, int end) {       if (start < end) {           int base = numbers[start]; // 選定的基準值(第一個數值作為基準值)           int temp; // 記錄臨時中間值           int i = start, j = end;           do {               while ((numbers[i] < base) && (i < end))                   i++;               while ((numbers[j] > base) && (j > start))                   j--;               if (i <= j) {                   temp = numbers[i];                   numbers[i] = numbers[j];                   numbers[j] = temp;                   i++;                   j--;               }           } while (i <= j);           if (start < j)               quickSort(numbers, start, j);           if (end > i)               quickSort(numbers, i, end);       }   }

 

Java演算法-快速排序

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.