1. 程式人生 > 其它 >排序——快排+歸併排序 簡述

排序——快排+歸併排序 簡述

技術標籤:演算法筆記指標演算法快速排序排序演算法

排序

快排是不穩定的,歸併是穩定的

快速排序 主要思想:分治(分界點從數組裡隨機取一個點

主要流程

  1. 確定分界點

    • 第一種方法:取左邊界 q[ I ]
    • 第二種方式:取中間值 q[ ( 1 + r) / 2]
    • 第三種方式 取右邊界 q[ r ]
  2. 調整區間

    ​ 使第一個區間裡的數都 小於等於 x (左半邊

    ​ 第二個區間裡的數都 大於等於 x (右半邊

  3. 遞迴處理左右兩端

    ​ 左邊排好序,右邊排好序

第二步中兩個小方法

方法一:

  • 設兩個陣列 a[ ] b[ ]

  • 檢查q[ l~r ]的數值

    • 小於等於X的插到a[ ]裡
    • 大於等於X的插到b[ ]裡
  • 分別將a[ ]、b[ ]插到q[ ]的第一區間和第二區間

方法二:

  • 設定兩個指標low和high,他們的初值分別為s和t。首先將X移至臨時變數,之後檢測指標high所指記錄,若q[ high ] 大於 X,則high減1,否則將q[ high ] 移至指標low所指向的位置;之後檢查指標low所指記錄,若q[ low ] 小於 X ,則 low 增 1,否則將q[ low ] 移至指標high所指位置;重複上述兩個方向的檢測,直到high和low指標指向同一位置
void quick_sort(int q[], int l, int r)
{
    if (l >= r) return;

    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    while (i < j)
    {
        do i ++ ; while (q[i] < x);
        do j -- ; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }
    quick_sort(q, l, j), quick_sort(q, j + 1, r);
}

歸併排序 主要思想:分治(以中間點為分解點) (分治方法和快排不同

主要流程

  1. 確定分界點 : mid = (1 + r) / 2 (左右兩邊的平均值,就是最中間的位置
  2. 遞迴排序 left(第一個序列) 和 right (第二個序列)
  3. 歸併 --》 把兩個有序的陣列合二為一 此步驟的時間複雜度是O(n)

在這裡插入圖片描述

如何歸併

首先通過遞迴排序保證兩個序列都是有序的,設定一個新的陣列res[ ] ,和兩個指標分別指向兩個序列的最小值。比較兩個指標指向的數值,把較小的指標指向的數值儲存到res[ ] 中,然後把這個指標後移一位(再次指向此序列中最小值),繼續比較兩指標指向的數值,然後放到陣列res[ ] 中。迴圈往復重複此操作,直至排序成功。

(如果兩個指標指向的數值相等,優先把第一個序列中的數值存到res中,這樣能保證排序是穩定的

void merge_sort(int q[], int l, int r)
{
    if (l >= r) return;

    int mid = l + r >> 1;
    merge_sort(q, l, mid);
    merge_sort(q, mid + 1, r);

    int k = 0, i = l, j = mid + 1;
    while (i <= mid && j <= r)
        if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
        else tmp[k ++ ] = q[j ++ ];

    while (i <= mid) tmp[k ++ ] = q[i ++ ];
    while (j <= r) tmp[k ++ ] = q[j ++ ];

    for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}

時間複雜度

平均的快排 和 歸併排序 的時間複雜度都是 nlog2n