算法导论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.  * 本文地址:http://mushiqianmeng.blog.51cto.com/3970029/730242
  53.  */ 
  54. public class MergeSort { 
  55.      
  56.     private static int[] input = new int[] { 21549867103 }; 
  57.  
  58.     /** 
  59.      * @param args 
  60.      */ 
  61.     public static void main(String[] args) { 
  62.         mergeSort(input); 
  63.         //打印数组 
  64.         printArray(); 
  65.     } 
  66.      
  67.     /** 
  68.      * 针对习题2.3-2改写,与伪代码不对应 
  69.      * @param array 
  70.      * @return 
  71.      */ 
  72.     private static int[] mergeSort(int[] array) { 
  73.         //如果数组的长度大于1,继续分解数组 
  74.         if (array.length > 1) { 
  75.             int leftLength = array.length / 2
  76.             int rightLength = array.length - leftLength; 
  77.             //创建两个新的数组 
  78.             int[] left = new int[leftLength]; 
  79.             int[] right = new int[rightLength]; 
  80.             //将array中的值分别对应复制到两个子数组中 
  81.             for (int i=0; i<leftLength; i++) { 
  82.                 left[i] = array[i]; 
  83.             } 
  84.             for (int i=0; i<rightLength; i++) { 
  85.                 right[i] = array[leftLength+i]; 
  86.             } 
  87.             //递归利用合并排序,排序子数组 
  88.             left = mergeSort(left); 
  89.             right = mergeSort(right); 
  90.             //设置初始索引 
  91.             int i = 0
  92.             int j = 0
  93.             for (int k=0; k<array.length; k++) { 
  94.                 //如果左边数据索引到达边界则取右边的值 
  95.                 if (i == leftLength && j < rightLength) { 
  96.                     array[k] = right[j]; 
  97.                     j++; 
  98.                 //如果右边数组索引到达边界,取左数组的值 
  99.                 } else if (i < leftLength && j == rightLength) { 
  100.                     array[k] = left[i]; 
  101.                     i++; 
  102.                 //如果均为到达则取,较小的值 
  103.                 } else if (i < leftLength && j < rightLength) { 
  104.                     if (left[i] > right[j]) { 
  105.                         array[k] = right[j]; 
  106.                         j++; 
  107.                     } else { 
  108.                         array[k] = left[i]; 
  109.                         i++; 
  110.                     } 
  111.                 }  
  112.             } 
  113.         }  
  114.         return array; 
  115.         /* 
  116.          * 复杂度分析: 
  117.          * 由于采用了递归,设解决长度为n的数组需要的时间为T(n),则分解成两个长度为n/2的子 
  118.          * 数组后,需要的时间为T(n/2),合并需要时间Θ(n)。所以有当n>1时,T(n)=2T(n/2)+Θ(n), 
  119.          * 当n=1时,T(1)=Θ(1) 
  120.          * 解这个递归式,设Θ(1)=c,(c为常量),则Θ(n)=cn。 
  121.          * 有上式可得T(n/2)=2T(n/4)+Θ(n/2),T(n/4)=2T(n/8)+Θ(n/4)....依次带入可得 
  122.          * 所以可以有T(n)=nT(1)+Θ(n)+2Θ(n/2)+4Θ(n/4)...+(2^lgn)Θ(n/(2^lgn)),其中共有lgn个Θ(n)相加。 
  123.          * 即T(n)=cn+cnlgn 
  124.          * 所以,时间复杂度为:Θ(nlgn) 
  125.          */ 
  126.     } 
  127.      
  128.     private static void printArray() { 
  129.         for (int i : input) { 
  130.             System.out.print(i + " "); 
  131.         } 
  132.     } 

 

     本文转自mushiqianmeng 51CTO博客,原文链接:http://blog.51cto.com/mushiqianmeng/730242,如需转载请自行联系原作者






相关文章
|
29天前
|
算法 调度
【软件设计师备考 专题 】算法探索:排序、查找、数值计算和字符串处理(二)
【软件设计师备考 专题 】算法探索:排序、查找、数值计算和字符串处理
32 0
|
1月前
|
算法 搜索推荐 Java
数据结构与算法(Java篇)笔记--希尔排序
数据结构与算法(Java篇)笔记--希尔排序
|
1月前
|
算法 Java
[Java·算法·中等] LeetCode15. 三数之和
[Java·算法·中等] LeetCode15. 三数之和
30 0
|
14天前
|
算法 安全 Java
java代码 实现AES_CMAC 算法测试
该代码实现了一个AES-CMAC算法的简单测试,使用Bouncy Castle作为安全提供者。静态变量K定义了固定密钥。`Aes_Cmac`函数接受密钥和消息,返回AES-CMAC生成的MAC值。在`main`方法中,程序对给定的消息进行AES-CMAC加密,然后模拟接收ECU的加密结果并进行比较。如果两者匹配,输出&quot;验证成功&quot;,否则输出&quot;验证失败&quot;。辅助方法包括将字节转为16进制字符串和将16进制字符串转为字节。
|
24天前
|
存储 搜索推荐 算法
【数据结构】八大排序之计数排序算法
【数据结构】八大排序之计数排序算法
11 4
|
24天前
|
搜索推荐 算法
【数据结构】八大排序之归并排序算法
【数据结构】八大排序之归并排序算法
20 5
|
24天前
|
搜索推荐 算法 编译器
【数据结构】八大排序之快速排序算法
【数据结构】八大排序之快速排序算法
35 4
|
24天前
|
存储 算法 JavaScript
Java入门高频考查算法逻辑基础知识3-编程篇(超详细18题1.8万字参考编程实现)
解决这类问题时,建议采取下面的步骤: 理解数学原理:确保你懂得基本的数学公式和法则,这对于制定解决方案至关重要。 优化算法:了解时间复杂度和空间复杂度,并寻找优化的机会。特别注意避免不必要的重复计算。 代码实践:多编写实践代码,并确保你的代码是高效、清晰且稳健的。 错误检查和测试:要为你的代码编写测试案例,测试标准的、边缘情况以及异常输入。 进行复杂问题简化:面对复杂的问题时,先尝试简化问题,然后逐步分析和解决。 沟通和解释:在编写代码的时候清晰地沟通你的思路,不仅要写出正确的代码,还要能向面试官解释你的
33 0
|
26天前
|
算法 Python
数据结构与算法 经典排序方法(Python)
数据结构与算法 经典排序方法(Python)
24 0
|
27天前
|
存储 算法 搜索推荐
【算法】七大经典排序(插入,选择,冒泡,希尔,堆,快速,归并)(含可视化算法动图,清晰易懂,零基础入门)
【算法】七大经典排序(插入,选择,冒泡,希尔,堆,快速,归并)(含可视化算法动图,清晰易懂,零基础入门)

热门文章

最新文章