/*
* mergeSort.cpp(歸併排序)
*
* Created on: 2012-4-20
* Author: jiyiqin
*
* 歸併排序:
* 分治法:
* 分治法思想,不斷將待排序陣列劃分成兩個部分。
* 直到問題最小(兩個元素)。
* 然後將兩個部分(各自有序)歸併到一起。
*
* 代價:
* 歸併的時間複雜度為o(n),整個排序演算法:
* 時間複雜度:o(n log n)
* 空間複雜度:o(n),需要兩個額外的陣列,但是總大小至多為n
*
* 穩定性:
* 穩定
*
*/
#include <iostream>
#include <math.h>
using namespace std;
#define MAXINT 65535
class MergeSort{
public:
/**
* 將a[low..m]和a[m+1..high]歸併到a[low...high]中
* 歸併前各自有序。
*
* 哨兵思想:
* 將兩個陣列歸併在一起的時候採用“哨兵”
* 即用無窮大放在兩個陣列各自的末尾
* 每次取兩個陣列中最小的放入a陣列,最先被
* 取完的陣列會遇到"哨兵",它總是大於另一個
* 沒有取完的陣列的元素,所以不需要判斷邊界條件
*
* 否則我們還要判斷,如果某個陣列提早結束,
* 還需要將另外一個沒有結束的陣列一次拷貝到a中
* 無疑增加了很多程式碼量
* 3,4,6,3,7,8,3,2,6,11,5
* */
/**
* 將陣列a的low->m部分和m+1->high部分歸併到low->high
* 呼叫此函式之前陣列a的兩邊已經各自有序
* */
void merge(int a[], int low, int m, int high){
int size1 = m-low+2; //low ~ m,額外申請一個存放哨兵
int size2 = high-m+1; //m+1 ~ high,額外申請一個存放哨兵
int *b1 = new int[size1];
int *b2 = new int[size2];
//拷貝a[low~m]到b1[0~size1-2]
for(int i=0;i<size1-1;i++)
b1[i] = a[i+low];
b1[i] = MAXINT;
//拷貝a[m+1~high]到b2[0~size-2]
for(int j=0;j<size2-1;j++)
b2[j] = a[j+m+1];
b2[j] = MAXINT;
/**
* merge b1 and b2:
* if b1 shorter than b2
* b1[size1-1](MAX) will greater than all b2[j]
*
* So MAX is great sentinel(哨兵)
* */
i = 0;
j = 0;
for(int k=low;k<=high;k++){
if(b1[i] <= b2[j]){
a[k] = b1[i++];
}
else{
a[k] = b2[j++];
}
}
}
/**
* 對陣列a進行分治法的歸併排序
* */
void mergeSort(int a[], int low, int high){
int m;
//歸併和氣泡排序的是<,二分查詢是<=
if(low < high)
{
m=(low+high)/2; //partition point
mergeSort(a, low, m);
mergeSort(a, m+1, high);
merge(a, low, m, high);
}
}
};
int main(){
MergeSort msort;
int a[11] = {12,2,16,30,8,128,4,10,20,6,18};
//sort
msort.mergeSort(a,0,10);
for(int i=0;i<11;i++){
cout<<a[i]<<" ";
}
cout<<endl;
return 0;
}