排序之 歸併排序

歸併排序

歸併排序是一種基於分治法的一種排序方法。它將要排序的序列分成兩個長度相等的子序列,爲每一個子序列進行排序,然後再將子序列合併成一個有序的序列。

比如對 10 4 6 3 8 2 5 7 這個數列排序

這裏寫圖片描述

這裏寫圖片描述

代碼:

template<class T>
void _Merge(T* arr, T* tmp, int begin, int end)
{
    int mid = ((begin ^ end) >> 1) + (begin & end);
    if (mid > begin)
        _Merge(arr, tmp, begin, mid);
    if (mid + 1 < end)
        _Merge(arr, tmp, mid + 1, end);
    int index = begin;
    int begin1 = begin;
    int end1 = mid;
    int begin2 = mid + 1;
    int end2 = end;
    while (begin1 <= end1 && begin2 <= end2){
        if (arr[begin1] < arr[begin2]){
            tmp[index++] = arr[begin1++];
        }
        else{
            tmp[index++] = arr[begin2++];
        }
    }
    while (begin1 <= end1){
        tmp[index++] = arr[begin1++];
    }
    while (begin2 <= end2){
        tmp[index++] = arr[begin2++];
    }
    while (begin <= end){
        arr[begin] = tmp[begin++];
    }

}

template<class T>
void MergeSort(T* arr, size_t n)
{
    assert(arr);
    int begin = 0;
    int end = n - 1;
    T* tmp = new T[n];
    _Merge(arr, tmp, begin, end);
    delete[] tmp;
}

爲了防止遞歸函數棧幀開銷 所以將元素數量小於13的小段待排序列用直接插入排序解決。

代碼:

template<class T>
void _Merge(T* arr, T* tmp, int begin, int end)
{
    int mid = ((begin ^ end) >> 1) + (begin & end);
    if (mid > begin){
        if (mid - begin + 1 > 13){
            _Merge(arr, tmp, begin, mid);
        }
        else{
            InsertSort(arr + begin, mid - begin + 1);
        }
    }

    if (mid + 1 < end){
        if (end - mid > 13){
            _Merge(arr, tmp, mid + 1, end);
        }
        else{
            InsertSort(arr + mid + 1, end - mid);
        }
    }

    int index = begin;
    int begin1 = begin;
    int end1 = mid;
    int begin2 = mid + 1;
    int end2 = end;
    while (begin1 <= end1 && begin2 <= end2){
        if (arr[begin1] < arr[begin2]){
            tmp[index++] = arr[begin1++];
        }
        else{
            tmp[index++] = arr[begin2++];
        }
    }
    while (begin1 <= end1){
        tmp[index++] = arr[begin1++];
    }
    while (begin2 <= end2){
        tmp[index++] = arr[begin2++];
    }
    while (begin <= end){
        arr[begin] = tmp[begin++];
    }

}

template<class T>
void MergeSort(T* arr, size_t n)
{
    assert(arr);
    int begin = 0;
    int end = n - 1;
    T* tmp = new T[n];
    _Merge(arr, tmp, begin, end);
    delete[] tmp;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章