合併排序——二路合併排序

  • 什麼是合併排序算法

合併排序就是將兩個或多個有序表合併成一個有序表,將兩個有序表合併成一個有序表稱爲二路合併數組

  • 算法描述 :ide

二路合併排序的基本思想是:對於兩個有序表合併,初始時, 把含有n個結點的待排序序列看做有n個長度爲1的有序子表所組成,將它們依次兩兩合併,獲得長度爲2的若干有序子表,再對這些子表進行兩兩合併,一直重複到長度爲n,排序完成。測試

  • 合併排序過程:spa

初始序列:排序

無標題.png

 

二路合併排序須要較大的輔助空間,輔助空間的大小與待排序序列同樣多。遞歸

(1)將14個原數據當作14個長度爲1的有序表(只有一個數據,確定是有序的)it

(2)將14個有序表兩兩合併,即將1,2合併3,4合併.....若是後面有單獨一個元素的,就單獨放在那裏,直接進入下一遍合併io

無標題.png

(3)通過第一遍的合併,獲得長度爲2的有序表序列,再將這些長度爲2的有序表序列進行兩兩合併。table

無標題.png

(4)通過第二遍合併以後,獲得長度爲4的有序表的序列,再將這些長度爲4的有序表進行兩兩合併。

無標題.png

(5)  通過上面的合併,獲得長度爲8的有序表,再將這些長度爲8的有序表進行兩兩合併。

 

無標題.png

 

  • 合併相鄰有序表 :

若是需合併的兩個有序表分別保存於數組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));

      */

   }

}

相關文章
相關標籤/搜索