C++_快速排序

快速排序:二十世紀十大算法之一 !

快速排序的基本實現

快速排序是一種基於交換的高效排序算法,它採用了分治法的思想。步驟以下:算法

  1. 從數列中選出一個數做爲基準數(樞軸,Pivot)
  2. 將數組進行劃分(Partition),將比基準數大的元素移至樞軸右側,將比基準數小的元素移至樞軸左側。
  3. 對左右兩區間分別進行第二步的劃分操做,知道每一個子區間只有一個元素。

快排最重要的步驟就是劃分了(Partition)。劃分的過程用通俗的語言講就是「挖坑」和「填坑」。數組

圖片較小,請原諒優化

劃分(Partition)


代碼:

int partition(int arr[], int left, int right)  //找基準數進行劃分
{
    int low = left + 1; //區間下端 
    int high = right;   //區間上端 
    int pivot = left;   //樞軸下標 
    int cur = pivot+1;  //存儲位置下標 

    for(int i=low; i<=high; i++)    //從下端到上端的遍歷
    {
        if(arr[i] < arr[pivot])
        {
            swap(arr[i], arr[cur]); //交換如今的值和存儲位置的值 
            cur++;  //將存儲位置變爲下一位 
        }
    }
    swap(arr[pivot], arr[cur-1]);   //將樞軸移至數組正確位置
    return cur-1;   //返回樞軸位置 
}

void quick_sort(int arr[], int left, int right) 
{
    if (left >= right)
        return;
    int mid = partition(arr, left, right);  //獲取樞軸位置 
    quick_sort(arr, left, mid - 1);     //下端區間遞歸 
    quick_sort(arr, mid + 1, right);    //上端區間遞歸 
}

時間複雜度分析

快排的時間複雜度在最壞狀況下是 O(n²),平均的時間複雜度是 O(n log n)ui

怎麼理解呢?其實很簡單。假設數列中有n個數,則遍歷一次的時間複雜度爲 O(n),須要遍歷至少 log (n + 1)次,最多 n次。.net

+Q1:爲何最少是 log (n + 1)次?
+A1:快速排序是採用分治法進行遍歷的,因此能夠當作一棵二叉樹,它遍歷的次數就是二叉樹的深度。而根據二叉樹的定義,它的深度至少爲 log (n + 1)。所以快速排序的遍歷次數至少是 log (n + 1)次。code

+Q2:爲何最可能是 n次遍歷?
+A2:這個應該比較好理解。仍然將快速排序看做一棵二叉樹,二叉樹的最大深度爲 n。因此快速排序的遍歷次數最可能是 n次。blog


快速排序的穩定性

快速排序是不穩定的算法,它不知足穩定排序算法的定義。 算法穩定性:假設在數列中存在 a[i] = a[j],若在排序以前,a[i] 在 a[j] 前面,而且排序後,a[i]仍然在 a[j]前面,則這個排序是穩定的!排序


That's all!Thank you for watching !

快速排序優化已更新!傳送門遞歸

相關文章
相關標籤/搜索