快速排序演算法程式碼實現
阿新 • • 發佈:2019-02-13
1 演算法介紹
快速排序是一個“交換類”的排序,以軍訓排隊為例,教官說:“第一個同學出列,其他人以他為中心,比他矮的全排到他的左邊,比他高的全排他右邊。”這就是一趟快速排序。可以看出,一趟快速排序是以一個“樞軸”為中心,將序列分成兩部分,樞軸的一邊全是比它小(或者小於等於)的,另一邊全是比他大(或者大於等於)的。
2 執行流程
原始序列:
49 38 65 97 76 13 27 49
i j(i和j開始時分別指向頭,尾元素)
進行第一趟快速排序,以第一個數49作為樞紐(通常都選第一個元素作為樞紐),整個過程是一個交替掃描和交換的過程。
1 )使用j,從序列最右端開始向前掃描,直到遇到比樞軸49小的數27,j停在這裡。
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大的數65,i停在這裡。
27 38 65 97 76 13 49
i j
4)將65交換到序列後端j的位置。
27 38 97 76 13 65 49
i j
5)使用j,交換掃描方向,從後向前掃描,直到遇到比樞軸49小的數13,j停在這裡。
27 38 97 76 13 65 49
i j
6)將13交換到i的位置。
27 38 13 97 76 65 49
i j
7)使用i,交換掃描方向,從前向後掃描,直到遇到比49大的數97,i停在這裡。
27 38 13 97 76 65 49
i j
8 )將97交換到j位置。
27 38 13 76 97 65 49
i j
9)使用j,交換掃描方向,直到遇到比49小的數,當掃描到i與j相遇時,說明掃描過程結束了。
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)。快速排序是遞迴進行的,遞迴需要棧的輔助,因此它需要的輔助空間較多。