思想
這是一種分治算法。將原始數組切分成較小的數組,直到每個小數組只有一項,然后在將小數組歸並為排好序的較大數組,直到最后得到一個排好序的最大數組。
代碼
function mergeSort(arr) {
const length = arr.length;
if (length === 1) { //遞歸算法的停止條件,即為判斷數組長度是否為1
return arr;
}
const mid = Math.floor(length / 2);
const left = arr.slice(0, mid);
const right = arr.slice(mid, length);
return merge(mergeSort(left), mergeSort(right)); //要將原始數組分割直至只有一個元素時,才開始歸並
}
function merge(left, right) {
const result = [];
let il = 0;
let ir = 0;
//left, right本身肯定都是從小到大排好序的
while( il < left.length && ir < right.length) {
if (left[il] < right[ir]) {
result.push(left[il]);
il++;
} else {
result.push(right[ir]);
ir++;
}
}
//不可能同時存在left和right都有剩余項的情況, 要么left要么right有剩余項, 把剩余項加進來即可
while (il < left.length) {
result.push(left[il]);
il++;
}
while(ir < right.length) {
result.push(right[ir]);
ir++;
}
return result;
}
性能分析
- 時間復雜度:最好、平均、最壞O(nlogn)
- 空間復雜度: O(n), 穩定
延伸:對比C語音的歸並排序
#include<stdio.h>
#include<stdlib.h>
void Merge(int *list,int *newlist,int s,int m,int t)
{
int i,j,k;
i=s;
j=m+1;
k=s;
while(i<=m&&j<=t)
{
if(list[i]<=list[j])
{
newlist[k]=list[i];
k++;
i++;
}
else
{
newlist[k]=list[j];
k++;
j++;
}
}
while(i<=m)//剩余的若是前一個序列,則其直接按並入newlist
{
newlist[k]=list[i];
i++;
k++;
}
while(j<=t)
{
newlist[k]=list[j];
j++;
k++;
}
}
void MSort(int *list,int *newlist,int s,int t)
{
int *newlist2;
int m;
newlist2=(int *)malloc((t-s+1)*sizeof(int));//分配一個新數組,和list等長
if(s==t)
{
newlist[s]=list[s];
}
else
{
m=(s+t)/2;
MSort(list,newlist2,s,m);//將list[s]……list[m]遞歸歸並為有序的newlist2[s]……newlist2[m]
MSort(list,newlist2,m+1,t);//將list[m+1]……list[t]遞歸歸並為有序的newlist2[m+1]……newlist2[t]
Merge(newlist2,newlist,s,m,t);//將newlist2[s]……newlist2[m]和newlist2[m+1]……newlist2[t]歸並到newlist[s]……newlist[t]
}
}
void MergeSort(int *list,int *newlist,int n)
{
MSort(list,newlist,0,n-1);
}
main()
{
int list[10],n=10,i,newlist[10];
printf("請輸入10個整數:\n");
for(i=0;i<10;i++)
{
scanf("%d",&list[i]);
}
MergeSort(list,newlist,10);
for(i=0;i<10;i++)
{
printf("%d",newlist[i]);
}
system("pause");
}