排序 - 归并排序(一)

归并排序的概念:


归并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序的序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体的有序序列。


首先,我们要注意以上的几个关键字,若干子序列,有序的


我们要保证我们将序列拆分成若干个子序列,并且各个子序列是有序的。


当子序列是有序的时,我们再采用两两合并的方法,并使得合并的序列也是有序的。


当把所有的子序列合并完成之后,整个序列也是有序的了


假设我们需要排序的数据是


{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++];
        }

    }

}

 

猜你喜欢

转载自alan-hjkl.iteye.com/blog/1591740