1. 程式人生 > >快速排序演算法程式碼實現

快速排序演算法程式碼實現

1 演算法介紹

快速排序是一個“交換類”的排序,以軍訓排隊為例,教官說:“第一個同學出列,其他人以他為中心,比他矮的全排到他的左邊,比他高的全排他右邊。”這就是一趟快速排序。可以看出,一趟快速排序是以一個“樞軸”為中心,將序列分成兩部分,樞軸的一邊全是比它小(或者小於等於)的,另一邊全是比他大(或者大於等於)的。

2 執行流程

原始序列:
    49 38 65 97 76 13 27 49
    i                     jij開始時分別指向頭,尾元素)
    進行第一趟快速排序,以第一個數49作為樞紐(通常都選第一個元素作為樞紐),整個過程是一個交替掃描和交換的過程。
    1
)使用j,從序列最右端開始向前掃描,直到遇到比樞軸49小的數27j停在這裡。 49 38 65 97 76 13 27 49 i j 2)將27交換到序列前端i的位置。 27 38 65 97 76 13 49 i j 3)使用i,交換掃描方向,從前向後掃描,直到遇到比較樞軸49大的數65i停在這裡。 27 38 65 97 76 13 49 i j 4)將65交換到序列後端j的位置。 27 38 97
76 13 65 49 i j 5)使用j,交換掃描方向,從後向前掃描,直到遇到比樞軸49小的數13j停在這裡。 27 38 97 76 13 65 49 i j 6)將13交換到i的位置。 27 38 13 97 76 65 49 i j 7)使用i,交換掃描方向,從前向後掃描,直到遇到比49大的數97i停在這裡。 27 38 13 97 76 65 49 i j 8
)將97交換到j位置。 27 38 13 76 97 65 49 i j 9)使用j,交換掃描方向,直到遇到比49小的數,當掃描到ij相遇時,說明掃描過程結束了。 27 38 13 76 97 65 49 ij 10)此時i等於j的這個位置就是樞軸49的最終位置,將49放入這個位置,第一趟快速排序結束。 27 38 13 49 76 97 65 49 ij

可以看出一次快速排序後,將原來的序列以49為樞軸,劃分為兩部分,49左邊的數都小於或等於它,右邊的數都大於或等於它。接下來按照同樣的方法對序列{27 38 13}和序列{76 97 65 49}分別進行快速排序。經過幾次這樣的快速排序,最終得到一個有序的序列。
快速排序程式碼如下:

#include <iostream>

void QuickSort(int *arr, int l, int r)
{
    int len = r;        // 儲存當前陣列的最後一個元素的座標
    int num = arr[l];   // 用來存放樞軸元素
    bool dir = 0;       // 用來表示移動方向

    /*一趟快速排序*/
    while (l != r)
    {
        if (dir == 0)
        {
            if (arr[r] < num)
            {
                arr[l] = arr[r];
                dir = 1;
            }
            else
            {
                r--;
            }
        }
        else
        {
            if (arr[l] > num)
            {
                arr[r] = arr[l];
                dir = 0;
            }
            else
            {
                l++;
            }
        }
    }
    arr[l] = num;               // 將樞軸元素放入最終位置
    if (l > 1)
    {
        QuickSort(arr, 0, l - 1);
    }
    if (len - l - 1 > 1)
    {
        QuickSort(arr, l + 1, len);
    }
}

int main()
{
    int arr[] = { 49, 38, 65, 97, 76, 13, 27, 49 };
    int len = 8;
    QuickSort(arr, 0, len - 1);

    for (int i = 0; i < len; i++)
    {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
    system("pause");
    return 0;
}

簡化後的快速排序演算法實現程式碼:

void QuickSort(int *pArray, int iBegin, int iEnd)
{
    if (iBegin < iEnd)
    {
        int iLeft = iBegin;
        int iRight = iEnd;
        int iPivot = pArray[iBegin];

        while (iLeft < iRight)
        {
            while (iLeft < iRight && pArray[iRight] >= iPivot)
            {
                iRight--;
            }
            if(iLeft < iRight) pArray[iLeft++] = pArray[iRight];

            while (iLeft < iRight && pArray[iLeft] <= iPivot)
            {
                iLeft++;
            }
            if(iLeft < iRight) pArray[iRight--] = pArray[iLeft];
        }
        pArray[iLeft] = iPivot;
        QuickSort(pArray, iBegin, iLeft - 1);
        QuickSort(pArray, iRight + 1, iEnd);
    }
}

效能分析

(1)時間複雜度分析
快速排序最好情況下的時間複雜度為O(nlog2n),待排序列越接近無序,本演算法效率越高。最壞情況下的時間複雜度為O(n2),待排序列越接近有序,本演算法效率越低。平均時間複雜度為O(nlog2n)。就平均時間而言,快速排序是所有排序演算法中最好的。快速排序的排序趟數與初始序列有關。
(2)空間複雜度分析
本演算法空間複雜度為O(log2n)。快速排序是遞迴進行的,遞迴需要棧的輔助,因此它需要的輔助空間較多。