算法导论Java实现-利用堆合并数组(习题6.5-8) 求高手指导

简介:

 《算法导论》习题6.5-8的实现,在时间复杂度方面,存在疑惑,望指教。具体问题写在代码的注释中。主要有两个方面:判断取出元素所在数组耗时问题和Java中switch语句的耗时问题。

本人菜鸟,欢迎讨论。

 
  1. package lhz.algorithm.chapter.six; 
  2.  
  3.  
  4. /** 
  5.  * 《算法导论》习题6.5-8: Give an Θ(nlgk)-time algorithm to merge k sorted lists into 
  6.  * one sorted list, where n is the total number of elements in all the input 
  7.  * lists. (Hint: Use a min-heap for k-way merging.)  
  8. * 本文地址:http://mushiqianmeng.blog.51cto.com/3970029/747716
  9.  * @author lihzh(苦逼coder) 
  10.  */ 
  11. public class Exercice658 { 
  12.  
  13.     // 给定3(k=3)个已排好序的数组,这里考虑简单情况, 
  14.     // 即所有数组包含的元素个数一致。 
  15.     // 注:因为已实现MaxHeapify算法,所以此处用最大到小排好序的数组举例 
  16.     private static int[] arrayOne = new int[] { 7431 }; 
  17.     private static int[] arrayTwo = new int[] { 10952 }; 
  18.     private static int[] arrayThree = new int[] { 121186 }; 
  19.      
  20.     // 已排好序中的数组中,元素的个数 
  21.     private static int length = arrayOne.length; 
  22.     // 已排好序的数组的个数 
  23.     private static int k = 3
  24.     // 所有数组中元素的总个数 
  25.     private static int n = length * k; 
  26.     // 合并后输出数组 
  27.     private static int[] output = new int[n]; 
  28.      
  29.     public static void main(String[] args) { 
  30.         mergeSortedArrays(); 
  31.         // 打印数组 
  32.         printArray(); 
  33.     } 
  34.  
  35.     /** 
  36.      * 合并已排序的数组,利用<code>PriorityQueue</code>中 的insert和extractMax算法实现 
  37.      * 复杂度分析: 
  38.      * 根据当前实现,复杂度应该为:Θ(nk),并不满足题意。 
  39.      * 但是所用思路,与习题参考中的思路一致,参考原文如下: 
  40.      * Given k sorted lists with a total of n elements show how to merge them in O(n lg k) time. Insert 
  41.      * all k elements a position 1 from each list into a heap. Use EXTRACT-MAX to obtain the _rst element 
  42.      * of the merged list. Insert element at position 2 from the list where the largest element originally 
  43.      * came from into the heap. Continuing in this fashion yields the desired algorithm. Clearly the 
  44.      * running time is O(n lg k). 
  45.      * 差异之处在于,当从堆中取出一个元素之后,需要知道这个元素原来所属数组,这里也需要去判断,这里耗时K。另外,在插入的时候, 
  46.      * 也需要判断 
  47.      */ 
  48.     private static void mergeSortedArrays() { 
  49.          
  50.         // 利用前面实现的优先级队列中的方法,构造一个容量为k=3的堆 
  51.         PriorityQueue priQueue = new PriorityQueue(k); 
  52.         int count = 0
  53.         //用于保存各数组当前插入元素索引位的数组 
  54.         int[] indexArray = new int[k]; 
  55.         int arrayChoice = 0
  56.         //初始情况,向堆中插入各数组首位元素 
  57.         //复杂度:Θ(klgk) 
  58.         priQueue.insert(arrayOne[0]); 
  59.         priQueue.insert(arrayTwo[0]); 
  60.         priQueue.insert(arrayThree[0]); 
  61.         for (int i = 0; i < n; i++) {// 该循环复杂度:Θ(n) 
  62.             // 取出当前最大值,复杂度Θ(lgk) 
  63.             int value = priQueue.extractMax(); 
  64.             count++; 
  65.             // 赋值 
  66.             output[n-count] = value; 
  67.             // 判断当前取出的最大元素所在数组,硬编码:(疑惑:复杂度Θ(k),因为最差会进行k次比较,此处如何优化) 
  68.             if (value == arrayOne[indexArray[0]]) { 
  69.                 arrayChoice = 0
  70.             } else if (value == arrayTwo[indexArray[1]]) { 
  71.                 arrayChoice = 1
  72.             } else { 
  73.                 arrayChoice = 2
  74.             } 
  75.             // 相应的索引位+1 
  76.             indexArray[arrayChoice]++; 
  77.             // 向堆中插入元素,如果备选数组中还有元素,则继续从该数组选取(疑惑:采用switch语句,复杂度是否降到Θ(lgk)以下) 
  78.             // 根据:http://hi.baidu.com/software_one/blog/item/254990dfd96aee205982ddcb.html 中介绍,似乎可以。 
  79.             // 望高手指导! 
  80.             switch (arrayChoice) { 
  81.             case 0 : 
  82.                 if (indexArray[0] < length) { 
  83.                     priQueue.insert(arrayOne[indexArray[0]]); 
  84.                 } 
  85.                 break
  86.             case 1 : 
  87.                 if (indexArray[1] < length) { 
  88.                     priQueue.insert(arrayTwo[indexArray[1]]); 
  89.                 } 
  90.                 break
  91.             case 2 : 
  92.                 if (indexArray[2] < length) { 
  93.                     priQueue.insert(arrayThree[indexArray[2]]); 
  94.                 }  
  95.                 break
  96.             } 
  97.         } 
  98.     } 
  99.  
  100.     private static void printArray() { 
  101.         for (int i : output) { 
  102.             System.out.print(i + " "); 
  103.         } 
  104.     } 

本例中使用到了之前实现的优先级队列中的方法,修改之前PriorityQueue类,增加构造函数

 
  1. public PriorityQueue(int capacity) { 
  2.         this.queue = new int[capacity]; 
  3.     } 
  4.      
  5.     public PriorityQueue() { 
  6.         this(DEFAULT_CAPACITY_VALUE); 
  7.     } 


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




相关文章
|
6天前
|
存储 算法 安全
探究‘公司禁用 U 盘’背后的哈希表算法与 Java 实现
在数字化办公时代,信息安全至关重要。许多公司采取“禁用U盘”策略,利用哈希表算法高效管理外接设备的接入权限。哈希表通过哈希函数将设备标识映射到数组索引,快速判断U盘是否授权。例如,公司预先将允许的U盘标识存入哈希表,新设备接入时迅速验证,未授权则禁止传输并报警。这有效防止恶意软件和数据泄露,保障企业信息安全。 代码示例展示了如何用Java实现简单的哈希表,模拟公司U盘管控场景。哈希表不仅用于设备管理,还在文件索引、用户权限等多方面助力信息安全防线的构建,为企业数字化进程保驾护航。
|
3月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
109 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
5天前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
24 2
|
3月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
58 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
2月前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明
|
3月前
|
存储 缓存 算法
Java 数组
【10月更文挑战第19天】Java 数组是一种非常实用的数据结构,它为我们提供了一种简单而有效的方式来存储和管理数据。通过合理地使用数组,我们能够提高程序的运行效率和代码的可读性。更加深入地了解和掌握 Java 数组的特性和应用,为我们的编程之旅增添更多的精彩。
41 4
|
3月前
|
存储 缓存 算法
提高 Java 数组性能的方法
【10月更文挑战第19天】深入探讨了提高 Java 数组性能的多种方法。通过合理运用这些策略,我们可以在处理数组时获得更好的性能表现,提升程序的运行效率。
50 2
|
3月前
|
存储 Java
Java“(array) <X> Not Initialized” (数组未初始化)错误解决
在Java中,遇到“(array) &lt;X&gt; Not Initialized”(数组未初始化)错误时,表示数组变量已被声明但尚未初始化。解决方法是在使用数组之前,通过指定数组的大小和类型来初始化数组,例如:`int[] arr = new int[5];` 或 `String[] strArr = new String[10];`。
110 2
|
3月前
|
Java
Java数组动态扩容和动态缩减
Java数组动态扩容和动态缩减
31 3
|
3月前
|
存储 算法 定位技术
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
这篇文章主要介绍了稀疏数组和队列的概念、应用实例以及如何使用数组模拟队列和环形队列的实现方法。
36 0
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列