歸併排序模板

御史大夫發表於2012-09-11
#include <iostream>
#include <string>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#define LL long long
#define MAXI 2147483647
#define MAXL 9223372036854775807
#define eps (1e-8)
#define dg(i) cout << "*" << i << endl;
using namespace std;

int a[10];

/*L:陣列左端下標,R:陣列右端下標,M:中間位置下標
此函式整合兩個陣列為一個有序陣列,這兩個陣列分別為{a[l],a[l+1],...,a[m]}
和{a[m+1],a[m+2],...,a[r]}.*/
void MergeArray(int L, int R, int M)
{
    vector<int> tmp;
    vector<int>::iterator it;
    int l = L, r = R, m = M + 1;
    //升序排列,故小的元素先壓入臨時陣列
    //當L<M不成立時,陣列{a[l],a[l+1],...,a[m]}已全部壓入臨時陣列
    //當m<R不成立時,陣列{a[m+1],a[m+2],...,a[r]}已全部壓入臨時陣列
    while(l <= M && m <= R)
    {
        if(a[l] < a[m])
            tmp.push_back(a[l++]);
        else
            tmp.push_back(a[m++]);
    }
    //將剩餘元素壓入臨時陣列
    while(l <= M)
        tmp.push_back(a[l++]);
    while(m <= R)
        tmp.push_back(a[m++]);
    for(it = tmp.begin(); it != tmp.end(); it++)
        a[L++] = *it;
}

/*L:陣列的左端下標,R:陣列的右端下標
該函式通過遞迴將陣列a不斷二分,最終將a拆分為一個個數,每一個數當做一個陣列;
在回溯時呼叫函式MergeArray(),從而將單元素陣列(即數字)重新合併為有序陣列*/
void MergeSort(int L, int R)
{
    int mid = (L + R) / 2; //陣列中間位置的下標
    if(L < R)
    {
        /*以下兩條語句將陣列二分。
        先處理陣列左半段,通過不斷地執行語句1將陣列左半段拆分為單個數字。
        在處理完左半段後,再執行語句2以處理陣列右半段。第三條語句在二分
        完成後回溯時執行,作用是合併數字為新的有序陣列*/
        MergeSort(L, mid); //語句1:處理陣列左半段
        MergeSort(mid + 1, R); //語句2:陣列右半段
        MergeArray(L, R, mid); //語句3:合併數字為新的有序陣列
    }
}

int main()
{
    int i;
    for(i = 0; i < 10; i++) cin >> a[i];
    MergeSort(0, 9);
    for(i = 0; i < 10; i++) cout << a[i] << " ";
    cout << endl;
    return 0;
}


相關文章