码迷,mamicode.com
首页 > 编程语言 > 详细

合并排序——二路合并排序

时间:2018-05-11 23:38:28      阅读:279      评论:0      收藏:0      [点我收藏+]

标签:合并排序   二路合并排序   java合并排序   

  • 什么是合并排序

  • 合并排序就是将两个或多个有序表合并成一个有序表,将两个有序表合并成一个有序表称为二路合并

    • 算法描述 :

    二路合并排序的基本思想是:对于两个有序表合并,初始时, 把含有n个结点的待排序序列看作有n个长度为1的有序子表所组成,将它们依次两两合并,得到长度为2的若干有序子表,再对这些子表进行两两合并,一直重复到长度为n,排序完成。

    • 合并排序过程:

    初始序列:

    技术分享图片

     

    二路合并排序需要较大的辅助空间,辅助空间的大小与待排序序列一样多。

    (1)将14个原数据看成14个长度为1的有序表(只有一个数据,肯定是有序的)

    (2)将14个有序表两两合并,即将1,2合并3,4合并.....如果后面有单独一个元素的,就单独放在那里,直接进入下一遍合并

    技术分享图片

    (3)经过第一遍的合并,得到长度为2的有序表序列,再将这些长度为2的有序表序列进行两两合并。

    技术分享图片

    (4)经过第二遍合并之后,得到长度为4的有序表的序列,再将这些长度为4的有序表进行两两合并。

    技术分享图片

    (5)  经过上面的合并,得到长度为8的有序表,再将这些长度为8的有序表进行两两合并。

     

    技术分享图片

     

    • 合并相邻有序表 :

    如果需合并的两个有序表分别保存于数组A中,其中一个序列保存在下标s~m的数组元素中,另一个序列保存在下标从m+1~n的数组元素中。合并把结果保存在数组R中。用变量i,j分别指向两个系列中需要比较的元素,变量k指向数组R中的序号,表示下一个要保存的数据的位置。

    (1)  取第1个系列的第i个元素A[i],与第2个系列的第1个元素比较A[j]。

    (2)  若A[i]<=A[j],则将A[i]复制到R[k]中,使i和k分别增加1.

    (3)若A[i]>A[j],则将A[j]复制到R[k]中,使j和k分别增加1

    (4)重复步骤1~3,直到一个序列复制完为止。

    (5)将另一个序列中比较的数据复制到R的剩余位置。

    //a[low...mid]a[mid+1,high]  b[low...high]

       void Merge(int a[],int b[],int low,int mid,int high){

          int i=low;

          int j=mid+1;

          int k=low;

         

          while(i<=mid && j<=high){

             if(a[i]<=a[j]){

                b[k++]=a[i++];

             }else{

                b[k++]=a[j++];

             }

          } private static void merge(int a[],int temp[],int low,int mid,int high){

       int i=low;

       int j=mid+1;

       int k=0;

      

       while(i<=mid && j<=high) {

          if(a[i]<=a[j]) {

             temp[k++]=a[i++];

          }else {

             temp[k++]=a[j++];

          }

       }

       while(i<=mid) {

          temp[k++]=a[i++];

       }

       while(j<=high) {

          temp[k++]=a[j++];

       }

       k = 0;

       // temp中的元素全部拷贝到原数组中

       while (low <= high) {

          a[low++] = temp[k++];

       }

    }

     

    • 归并排序:

    (1)  二路归并排序将a[low...high]中的记录归并排序后放入temp[low...high]中。当序列长度等于1时,递归结束,否则:

    a)     将当前序列一分为二,求出分裂点mid=(low+high)/2

    b)    对子序列a[low..mid]递归,进行归并排序,结果放入temp[low...mid]

    c)     对子序列a[mid+1,high],进行归并排序,结果放入temp[mid+1,high]

    d)    调用Merge将有序的两个子序列a[low..mid]与a[mid+1,high]归并为一个有序的序列temp[low...high]

    /**

     * sort

     */

    public static void sort(int a[],int temp[],int low,int high) {

       if(low<high) {

           int mid=(low+high)/2;

           sort(a,temp,low,mid);

           sort(a,temp,mid+1,high);

           merge(a,temp,low,mid,high);

       }

    }

    • 算法实例:

    public class MergeSort {

       /**

        * 相邻有序子序列进行合并

        *   a[low...mid] a[mid+1,high]

        */

       private static void merge(int a[],int temp[],int low,int mid,int high){

          int i=low;

          int j=mid+1;

          int k=0;

         

          while(i<=mid && j<=high) {

             if(a[i]<=a[j]) {

                temp[k++]=a[i++];

             }else {

                temp[k++]=a[j++];

             }

          }

          while(i<=mid) {

             temp[k++]=a[i++];

          }

          while(j<=high) {

             temp[k++]=a[j++];

          }

          k = 0;

          // temp中的元素全部拷贝到原数组中

          while (low <= high) {

             a[low++] = temp[k++];

          }

       }

      

       public static void sort(int a[],int temp[],int low,int high) {

          if(low<high) {

              int mid=(low+high)/2;

              sort(a,temp,low,mid);

              sort(a,temp,mid+1,high);

              merge(a,temp,low,mid,high);

          }

       }

       public static void sort(int []arr){

            int []temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间

            sort(arr,temp,0,arr.length-1);

        }

       public static void main(String[] args) {

          int arr[]= {56,41,26,32,55,75,2,63,12,19,58,77,34,95};

          sort(arr);

          System.out.println("排序结果:"+Arrays.toString(arr));

         

          /*

          测试,合并有序子序列

          int arr[]= {1,3,5,2,4,6};

          int temp[]=new int[arr.length];

          merge(arr, temp, 0, 2,   arr.length-1);

         

          System.out.println("排序结果:"+Arrays.toString(arr));

          System.out.println("排序结果:"+Arrays.toString(temp));

          */

       }

    }



    合并排序——二路合并排序

    标签:合并排序   二路合并排序   java合并排序   

    原文地址:http://blog.51cto.com/13733462/2115396

    (0)
    (0)
       
    举报
    评论 一句话评论(0
    登录后才能评论!
    © 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
    迷上了代码!