算法導論Java實現-合併排序(包含習題2.3-2)

 
  1. package lhz.algorithm.chapter.two; 
  2.  
  3. /** 
  4.  * 《合併排序》,利用分治思想進行排序。(針對習題2.3-2) 
  5.  * 《算法導論》原文摘要: 
  6.  * The  merge sort algorithm closely follows the divide -and-conquer paradigm . Intuitively, it  
  7.  *  operates as follows.  
  8.  * •   Divide: Divide the  n-element sequence to be sorted into two subsequences of  n/2  
  9.  *     elements each.  
  10.  * •   Conquer: Sort the two subsequences recursively using merge sort.  
  11.  * •   Combine: Merge the two sorted subsequences to produce the sorted answer.  
  12.  * The recursion "bottoms out" when the sequence to be sorted has length 1,  in which case there  
  13.  * is no work to be done, since every sequence  of length 1 is already in sorted order.  
  14.  * The key operation of the merge sort algorithm is  the merging of two sorted sequences in the  
  15.  * "combine" step. To perform the merging,  we use an auxiliary procedure MERGE( A,  p,  q,  r ),  
  16.  * where A is an array and  p,  q, and r  are indices numbering elements of the array such that  p ≤  q <  r . The procedure assumes that the subarrays  A[p  q] and A[q + 1   r ] are in sorted order.  
  17.  * It  merges  them to form a single sorted subarray that replaces the current subarray  A[p  r].  
  18.  *  
  19.  * Our MERGE procedure takes time Θ ( n), where n = r - p + 1 is the number of 
  20.  * elements being merged, and it works as follows. Returning to our card-playing 
  21.  * motif , suppose we have two piles of cards face up on a table. Each pile is 
  22.  * sorted, with the smallest cards on top. We wish to merge the two piles into a 
  23.  * single sorted output pile, which is to be face down on the table. Our basic 
  24.  * step consists of choosing the smaller of the two cards on top of the face-up 
  25.  * piles, removing it from its pile (which exposes a new top card), and placing 
  26.  * this card face down onto the output pile. We repeat this step until one input 
  27.  * pile is empty, at which time we just take the remaining input pile and place 
  28.  * it f ace down onto the output pile. Computationally, each basic step takes 
  29.  * constant time, since we are checking just two top cards. Since we perform at 
  30.  * most n basic steps, merging takes Θ( n) time. 
  31.  *  
  32.  * 僞代碼: 
  33.  *  MERGE(A, p, q, r)  
  34.  *1  n1  ← q -  p + 1  
  35.  *2  n2  ← r -  q  
  36.  *3  create arrays  L[1   n1  + 1] and  R[1   n2  + 1]  
  37.  *4  for  i ← 1  to n1   
  38.  *5       do L[i] ← A[p +  i - 1]  
  39.  *6  for  j ← 1  to n2   
  40.  *7       do R[j] ← A[q +  j]  
  41.  *8  L[n1  + 1] ← ∞ (∞代表到達最大值,哨兵位) 
  42.  *9  R[n2  + 1] ← ∞  
  43.  *10  i ← 1  
  44.  *11  j ← 1  
  45.  *12  for  k ← p to r  
  46.  *13       do if  L[i] ≤ R[j]  
  47.  *14              then A[k] ← L[i]  
  48.  *15                   i ← i + 1  
  49.  *16              else A[k] ← R[j]  
  50.  *17                   j ← j + 1  
  51.  *@author lihzh(苦逼coder) 
  52.  */ 
  53. public class MergeSort { 
  54.      
  55.     private static int[] input = new int[] { 21549867103 }; 
  56.  
  57.     /** 
  58.      * @param args 
  59.      */ 
  60.     public static void main(String[] args) { 
  61.         mergeSort(input); 
  62.         //打印數組 
  63.         printArray(); 
  64.     } 
  65.      
  66.     /** 
  67.      * 針對習題2.3-2改寫,與僞代碼不對應 
  68.      * @param array 
  69.      * @return 
  70.      */ 
  71.     private static int[] mergeSort(int[] array) { 
  72.         //如果數組的長度大於1,繼續分解數組 
  73.         if (array.length > 1) { 
  74.             int leftLength = array.length / 2
  75.             int rightLength = array.length - leftLength; 
  76.             //創建兩個新的數組 
  77.             int[] left = new int[leftLength]; 
  78.             int[] right = new int[rightLength]; 
  79.             //將array中的值分別對應複製到兩個子數組中 
  80.             for (int i=0; i<leftLength; i++) { 
  81.                 left[i] = array[i]; 
  82.             } 
  83.             for (int i=0; i<rightLength; i++) { 
  84.                 right[i] = array[leftLength+i]; 
  85.             } 
  86.             //遞歸利用合併排序,排序子數組 
  87.             left = mergeSort(left); 
  88.             right = mergeSort(right); 
  89.             //設置初始索引 
  90.             int i = 0
  91.             int j = 0
  92.             for (int k=0; k<array.length; k++) { 
  93.                 //如果左邊數據索引到達邊界則取右邊的值 
  94.                 if (i == leftLength && j < rightLength) { 
  95.                     array[k] = right[j]; 
  96.                     j++; 
  97.                 //如果右邊數組索引到達邊界,取左數組的值 
  98.                 } else if (i < leftLength && j == rightLength) { 
  99.                     array[k] = left[i]; 
  100.                     i++; 
  101.                 //如果均爲到達則取,較小的值 
  102.                 } else if (i < leftLength && j < rightLength) { 
  103.                     if (left[i] > right[j]) { 
  104.                         array[k] = right[j]; 
  105.                         j++; 
  106.                     } else { 
  107.                         array[k] = left[i]; 
  108.                         i++; 
  109.                     } 
  110.                 }  
  111.             } 
  112.         }  
  113.         return array; 
  114.         /* 
  115.          * 複雜度分析: 
  116.          * 由於採用了遞歸,設解決長度爲n的數組需要的時間爲T(n),則分解成兩個長度爲n/2的子 
  117.          * 數組後,需要的時間爲T(n/2),合併需要時間Θ(n)。所以有當n>1時,T(n)=2T(n/2)+Θ(n), 
  118.          * 當n=1時,T(1)=Θ(1) 
  119.          * 解這個遞歸式,設Θ(1)=c,(c爲常量),則Θ(n)=cn。 
  120.          * 有上式可得T(n/2)=2T(n/4)+Θ(n/2),T(n/4)=2T(n/8)+Θ(n/4)....依次帶入可得 
  121.          * 所以可以有T(n)=nT(1)+Θ(n)+2Θ(n/2)+4Θ(n/4)...+(2^lgn)Θ(n/(2^lgn)),其中共有lgn個Θ(n)相加。 
  122.          * 即T(n)=cn+cnlgn 
  123.          * 所以,時間複雜度爲:Θ(nlgn) 
  124.          */ 
  125.     } 
  126.      
  127.     private static void printArray() { 
  128.         for (int i : input) { 
  129.             System.out.print(i + " "); 
  130.         } 
  131.     } 

轉自木石大哥的博客    http://mushiqianmeng.blog.51cto.com/#
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章