1. 程式人生 > >快速排序–劃分(上)

快速排序–劃分(上)

快速排序的核心操作就是劃分,在(java資料結構與演算法)中也單獨將劃分劈出一個章節來說,現在大家應該已經知道通過設定兩個指標分別從陣列的左右兩側向中間進行掃描的方式來實現劃分操作(此方法就是排序––快速排序(二)中給出的一個初步劃分方案,並且那是在特殊序列並選擇了特殊軸樞元素情況下才容易讓人理解),當隨機選擇一個不能將整個序列平均劃分的時候個人認為該方法不太好理解,現按照自己的理解來寫一個正確的快速排序程式碼,並嘗試用該方法過度到通用方法中(這裡要感謝我同事給我的幫助,因為根據他給的初步方法才有了下面的內容),該篇先寫一個正確的劃分程式碼。

1、假如讓我們自己來實現一個劃分演算法,首先會從已知序列中選擇一個元素作為軸樞(注意該選擇是隨機的,我們的重點先放在如何寫一個正確的劃分演算法上面)。

2、從序列的左邊開始掃描(設指標變數為i),如果遇到一個小於等於軸樞元素的數就直接跳過進行下個元素的比較;如果遇到一個大於軸樞的元素就要從下一個元素(設指標變數為j初始值為i+1)開始尋找一個小於等於軸樞的元素並與該元素交換。

3、當變數j到達序列的末尾時說明再也沒有小於等於軸樞的元素了表示劃分結束或者當變數i到達序列的末尾時說明序列所有的元素都小於等於軸樞元素,所以變數i的本質是左右序列的邊界位置(邊界位置的元素永遠大於軸樞或者由於超過了序列的長度而不存在,或者換個說法i-1位置的元素小於等於軸樞元素),而變數j的本質是用來尋找小於等於軸樞元素的。當劃分結束的時候還要將軸樞元素與i-1位置上的元素進行交換!這裡假設序列共有元素n個,第一趟排序實際比較次數為n次。這與通常的劃分演算法(通過左右兩邊向中間掃描)比較次數一樣,只是這裡是由左向右的掃描方法,個人認為這種方式更好理解,程式碼如下:

public int partition(int from, int to) {
        int partPos = from;
        int ltePos = from + 1;
        int pivotPos = -1;
        while (true) {
            int comp = 0;
            while (partPos <= to && (comp = comparePivot(partPos)) <= 0) {
                if (comp == 0) {
                    pivotPos = partPos;
                }
                partPos++;
            }
            ltePos = partPos + 1;
            while (ltePos <= to && comparePivot(ltePos) > 0) {
                ltePos++;
            }
            if (partPos > to || ltePos > to) {
                break;
            }
            swap(partPos, ltePos);
        }
        int actPartPos = partPos - 1;
        swap(pivotPos, actPartPos);
        return actPartPos;
   &