歸並排序是建立在歸並操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個非常典型的應用。 歸並操作的過程如下: 1.申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合並後的序列 2.設定兩個指針,最初位置分別為兩個已經排序序列的起始位置 3.比較兩個指針所指向的元素,選擇相對小的元素放入到合並空間,並移動指針到下一位置 4.重復步驟3直到某一指針達到序列尾 5.將另一序列剩下的所有元素直接復制到合並序列尾 簡單地說,歸並排序就是將序列不斷地劃分,直到每個序列只有一個元素(一個元素的序列肯定是有序的),然後這些有序序列不斷歸並,合成新的有序序列,最後,歸並成全部有序的序列。 這幅 Wiki 的圖很直觀地解釋了歸並排序: 最差時間復雜度 O(n logn) 最優時間復雜度 O(n) 平均時間復雜度 O(n logn) 穩定性:穩定 實現:
#include <iostream>
using namespace std;
//歸並操作,將有兩個個有序數列 num[start...mid] 和 num[mid...end] 歸並並。
//歸並至 sorted 序列,然後復制回原數組
void merge(int num[], int start, int mid, int end, int sorted[])
{
int i = start, j = mid + 1;
int m = mid, n = end;
int k = 0;
//每次比較兩個元素,直到某個序列到達末尾
while (i <= m && j <= n)
{
if (num[i] <= num[j])
sorted[k++] = num[i++];
else
sorted[k++] = num[j++];
}
//將序列中剩余元素直接復制到 sorted 序列尾
while (i <= m)
sorted[k++] = num[i++];
while (j <= n)
sorted[k++] = num[j++];
//將排序好的序列寫回原數組
for (i = 0; i < k; i++)
num[start + i] = sorted[i];
}
void mergesort(int a[], int start, int end, int sorted[])
{
if (start < end)
{
//進行分治
int mid = (start + end) / 2;
mergesort(a, start, mid, sorted);
mergesort(a, mid + 1, end, sorted);
merge(a, start, mid, end, sorted);
}
}
bool MergeSort(int num[], int n)
{
int *p = new int[n];
if (p == NULL)
return false;
mergesort(num, 0, n - 1, p);
delete[] p;
return true;
}
//簡單測試,建議數據不要太大,那是在刷屏啊 o(╯□╰)o
int main()
{
int n;
//測試 n 個隨機數的排序
while(cin>>n)
{
int *p = new int[n];
if (!p)
{
cout<<"Failed..."<<endl;
continue;
}
for(int i=0;i<n;++i)
p[i] = rand();
bool flag = MergeSort(p,n);
if(!flag)
{
cout<<"Failed..."<<endl;
continue;
}
for(int i=0;i<n;++i)
cout<<p[i]<<' ';
cout<<endl;
delete []p;
}
return 0;
}