算法导论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 ,如需转载请自行联系原作者




相关文章
|
3月前
|
Java
【Java基础面试三十二】、new String(“abc“) 是去了哪里,仅仅是在堆里面吗?
这篇文章解释了Java中使用`new String("abc")`时,JVM会将字符串直接量"abc"存入常量池,并在堆内存中创建一个新的String对象,该对象会指向常量池中的字符串直接量。
|
12天前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
46 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
22天前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
37 0
|
3月前
|
存储 算法 Java
惊!Java程序员必看:JVM调优揭秘,堆溢出、栈溢出如何巧妙化解?
【8月更文挑战第29天】在Java领域,JVM是代码运行的基础,但需适当调优以发挥最佳性能。本文探讨了JVM中常见的堆溢出和栈溢出问题及其解决方法。堆溢出发生在堆空间不足时,可通过增加堆空间、优化代码及释放对象解决;栈溢出则因递归调用过深或线程过多引起,调整栈大小、优化算法和使用线程池可有效应对。通过合理配置和调优JVM,可确保Java应用稳定高效运行。
131 4
|
3月前
|
存储 算法 Java
解释 Java 堆空间和垃圾收集
【8月更文挑战第22天】
32 0
|
12天前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
36 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
15天前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
17 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
15天前
|
存储 算法 Java
🏗️Java零基础:深入了解Java 堆
【10月更文挑战第2天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
17 3
|
17天前
|
Java 数据安全/隐私保护
JAVA经典习题详解
JAVA经典习题详解
15 4
|
15天前
|
存储 算法 定位技术
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
这篇文章主要介绍了稀疏数组和队列的概念、应用实例以及如何使用数组模拟队列和环形队列的实现方法。
18 0
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列