归并排序的概念:
归并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序的序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体的有序序列。
首先,我们要注意以上的几个关键字,若干子序列,有序的
我们要保证我们将序列拆分成若干个子序列,并且各个子序列是有序的。
当子序列是有序的时,我们再采用两两合并的方法,并使得合并的序列也是有序的。
当把所有的子序列合并完成之后,整个序列也是有序的了
假设我们需要排序的数据是
{50,10,90,30,70,40,80,60,20}
一开始,我们需要将其分成小的序列
首先,我们将其的长度折半,然后,在这折半,一直到1为止,
这样,上面的数组被分成两端,如果两边个数不能相等,我们默认让左侧多一个
1次折半的结果就是{50,10,90,30,70} ,{40,80,60,20}
2次折半的结果就是{50,10,90},{30,70} , {40,80},{60,20}
3次折半的结果就是{50,10},{90} {30} ,{70} ,{40},{80} ,{60},{20}
4次折半的结果就是{50},{10},{90},{30},{70} ,{40},{80},{60},{20}
然后,我们在将其两两合并,并做排序处理。
首先,50和10合并,30和70合并,40和80合并,60和20合并
也许有同学会问,为什么不是90和30合并呢? 其实它们合并也是可以的。
我这样合并的目的是为了和后面的算法相统一,我从哪里拆分的,就从哪里合并起来
1次合并的结果就是{10,50},{90},{30},{70},{40},{80},{20},{60}
2次合并的结果就是{10,50,90},{30,70},{40,80},{20,60}
3次合并的结果就是{10,30,50,70,90} {20,40,60,80}
4次合并的结果就是{10,20,30,40,50,60,70,80,90}
这样我们就完成了排序
下面给出C代码
void MergeSort(SqList *L){ MSort(L->r,L->r,1,L->length); } void MSort(int SR[],int TR1[],int s,int t){ int m; int TR2[MAXSIZE+1]; if(s==t){ TR1[s] = SR[s]; }else{ m = (s+t)/2; MSort(SR,TR2,s,m); MSort(SR,TR2,m+1,t); Merge(TR2,TR1,s,m,t); } } void Merge(int SR[],int TR[],int i, int m, int n){ int j,k,l; for(j=m+1,k=i;i<=m && j<=n;k++){ if(SR[i]<SR[j]){ TR[k] = SR[i+1]; }else{ TR[k] = SR[j++]; } } if(i<=m){ for(l=0;l<=m-i;l++){ TR[k+l] = SR[i+l]; } } if(j<=n){ for(l=0;l<n-j;l++){ TR[k+l] = SR[j+l]; } } }
这部分算法越解释,越乱,
下面给出一张它算法的原理图,有心的同学可以继续研究,
下面给出java版本的实现
package com.fortune.test;
/**
* Created with IntelliJ IDEA.
* User: liupeng
* Date: 12-7-13
* Time: 下午1:04
*/
public class TestMergeSort {
public static void main(String args[]) {
int[] num = {51, 38, 49, 27, 62, 05, 16};
int[] num1 = new int[7];
num = mergeSort(num, 0, num.length - 1, num1);
for (int i : num) {
System.out.print(i + " ");
}
}
private static int[] mergeSort(int[] num, int s, int t, int[] num1) {
int m;
int[] num2 = new int[t + 1];
if (s == t) {
num1[s] = num[s];
} else {
m = (s + t) / 2;
mergeSort(num, s, m, num2);
mergeSort(num, m + 1, t, num2);
merge(num2, s, m, t, num1);
}
return num1;
}
private static void merge(int[] num, int l, int m, int n, int[] num1) {
System.out.println("l=" + l + "m=" + m + "n=" + n);
int i, j, k;
i = l;
j = m + 1;
k = l;
while (i <= m && j <= n) {
if (num[i] < num[j]) {
num1[k++] = num[i++];
} else {
num1[k++] = num[j++];
}
}
while (i <= m) {
num1[k++] = num[i++];
}
while (j <= n) {
num1[k++] = num[j++];
}
}
}