合併排序(歸併排序)的遞歸和非遞歸

輸入:先輸入進行合併排序元素的個數,然後依次隨機輸入(或隨機生成)每個數字。
輸出:元素排序後的結果,數字之間不加任何標識符。
示例:輸入:8 11 1 2 4 8 6 15 8,輸出:1 2 4 6 8 8 11 15

#include<iostream>
using namespace std;
//合併排序/歸併排序
template<typename T>
void __mergeSort(T arr[], int l, int mid, int r)
{
    // 經測試,傳遞aux數組的性能效果並不好
    //T aux[r - l + 1];
    T *aux = new T[r - l + 1];
    for (int i = l; i <= r; i++)
        aux[i - l] = arr[i];//賦值 

    int i = l, j = mid + 1;
    for (int k = l; k <= r; k++){

        if (i > mid)
        {
            arr[k] = aux[j - l]; j++;
        }
        else if (j > r)
        {
            arr[k] = aux[i - l]; i++;
        }
        else if (aux[i - l] < aux[j - l])
        {
            arr[k] = aux[i - l]; i++;
        }
        else
        {
            arr[k] = aux[j - l]; j++;
        }
    }
    delete[]aux;
}
template<typename T>
void MergeSort(T arr[], int l, int r)
{
    if (l >= r)
    {
        return;
    }
    int mid = (r + l) / 2;
    MergeSort(arr, l, mid);//先將這個運行到底             ①
    MergeSort(arr, mid + 1, r);//這個,mid不是那個例如數組大小爲6,mid=3那個mid,而是上步①結束時的mid
    __mergeSort(arr, l, mid, r);//這個排序,排的是第一對(1邊1個),在排第二對。。。然後下一輪第一對(1邊2個)相排.。。
}
int main()
{
    int n;
    cin >> n;
    int *arr = new int[n];
    for (int i = 0; i < n; i++)
    {
        cin >> arr[i];
    }
    MergeSort(arr, 0, n-1);
    for (int i = 0; i < n; i++)
    {
        cout << arr[i] << " ";
    }
    delete[]arr;
    return 0;
}


--------------------------------------------------------------------------
優化:
#include<iostream>
using namespace std;
//合併排序/歸併排序
template<typename T>
void __mergeSort(T arr[], int l, int mid, int r)
{
    // 經測試,傳遞aux數組的性能效果並不好
    //T aux[r - l + 1];
    T *aux = new T[r - l + 1];
    for (int i = l; i <= r; i++)
        aux[i - l] = arr[i];//賦值 

    int i = l, j = mid + 1;
    for (int k = l; k <= r; k++){

        if (i > mid)
        {
            arr[k] = aux[j - l]; j++;
        }
        else if (j > r)
        {
            arr[k] = aux[i - l]; i++;
        }
        else if (aux[i - l] < aux[j - l])
        {
            arr[k] = aux[i - l]; i++;
        }
        else
        {
            arr[k] = aux[j - l]; j++;
        }
    }
    delete[]aux;
}
template<typename T>
void MergeSort(T arr[], int l, int r)
{
    if (l >= r)
    {
        return;
    }
    //優化1:
    /*if (r - l <= 15)//由於小數量的排序,插入排序比歸併更划算,所以這選擇這樣,這個數是測試得到的,不一定是15
    {
        insertionSort1(arr, l, r);
    }*/


    int mid = (r + l) / 2;
    MergeSort(arr, l, mid);//先將這個運行到底             ①
    MergeSort(arr, mid + 1, r);//這個,mid不是那個例如數組大小爲6,mid=3那個mid,而是上步①結束時的mid
    __mergeSort(arr, l, mid, r);

    //優化2:
    /*
    if(arr[mid] > arr[mid + 1])//例如這裏第一次是1個和1個比,比完後,兩個元素(數組A)和兩個元素(數組B)比,這兩個數組裏的元素是已經排好序的,所以只需要比較arr[mid] 和 arr[mid + 1]就知道還需不需要去比較;
    {
        __mergeSort(arr, l, mid, r);//這個排序,排的是第一對(1邊1個),在排第二對。。。然後下一輪第一對(1邊2個)相排.。。
    }
    */
}
int main()
{
    int n;
    cin >> n;
    int *arr = new int[n];
    for (int i = 0; i < n; i++)
    {
        cin >> arr[i];
    }
    MergeSort(arr, 0, n-1);
    for (int i = 0; i < n; i++)
    {
        cout << arr[i] << " ";
    }
    delete[]arr;
    return 0;
}
//非遞歸
自底向上:  迭代的方式
template <typename T>
void mergeSortBU(T arr[], int n){
    for( int sz = 1; sz <= n ; sz += sz )//一次加sz,(下面的循環,sz每加一次sz,下面的數組A和數組B就會擴大1倍)
        for( int i = 0 ; i+size < n ; i += sz+sz )//排序用的,第一次排第一對(數組A和數組B),然後第二對...第三對...//i+size < n 是爲了防止下面中間的元素的越界
           // 對 arr[i...i+sz-1] 和 arr[i+sz...i+2*sz-1] 進行歸併
            __merge(arr, i, i+sz-1, min(i+sz+sz-1,n-1) );// min(i+sz+sz-1,n-1)由於最右邊的元素可能超過界限,所以用min()就可以起到一個限制作用
}
//非遞歸的優化
    for( int i = 0 ; i < n ; i += 16 )
        insertionSort(arr,i,min(i+15,n-1));

    for( int sz = 16; sz <= n ; sz += sz )
        for( int i = 0 ; i < n - sz ; i += sz+sz )
            if( arr[i+sz-1] > arr[i+sz] )
                __merge(arr, i, i+sz-1, min(i+sz+sz-1,n-1) );
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章