`
robertliudeqiang
  • 浏览: 123283 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

基于java优先队列(PriorityQueue)的多路排序算法(含代码)

阅读更多
归并排序用来合并排好序的数组,常用于外部排序,常见的归并排序是对两个数组进行归并,如果两个数组长度为m和n的话,比较的时间最大是m+n。

新的问题是,如果有多个排好序的数组,如果进行归并? 一种可以想到的方法是:逐个进行归并排序(第一个数组和第二个数组合并,合并和的数组再和第三个数组合并...),这种情况下时间复杂度是O(n*n)。

算法导论里提到过一个用堆来进行多路排序的算法,时间复杂度是nlogn,java里面的PriorityQueue就是现成的堆的结构,实现起来还是比较方便的,代码如下:


用到的内部数据结构:
	// 如果用链表存储数据,就不用这么麻烦了,
	// 用数组的话,使用一个内部类保存当前值对应的数组即其在数组中的索引
	// 需要实现Comparable接口,否则PriorityQueue无法对对象进行比较
	private static class Element implements Comparable<Element> {
		int value;
		int whichArray;
		int whichIndex;

		Element(int value, int whichArray, int whichIndex) {
			this.value = value;
			this.whichArray = whichArray;
			this.whichIndex = whichIndex;
		}

		@Override
		public int compareTo(Element o) {
			if (value < o.value)
				return -1;
			if (value > o.value)
				return 1;
			return 0;
		}
	}


主运行程序
	// 程序比较丑陋是因为java不支持基本类型的泛型和动态变量名
	public static void main(String[] args) {
		// The arrays used for multi merge sort
		Integer[] a = { 6, 19, 24, 31 };
		Integer[] b = { 2, 5, 9, 67 };
		Integer[] c = { 8, 20, 76, 389, 399 };
		Integer[] d = { 266, 388, 736, 736, 3923 };
		Integer[] e = { 38, 234, 1021, 7136, 39342 };

		HashMap<Integer, Integer[]> map = new HashMap<Integer, Integer[]>();
		map.put(0, a);
		map.put(1, b);
		map.put(2, c);
		map.put(3, d);
		map.put(4, e);

		int arrSize = map.size();
		// The PriorityQueue used for sort
		PriorityQueue<Element> pq = new PriorityQueue<Element>(arrSize);

		// Put the first element of each array to the PriorityQueue
		for (int i = 0; i < arrSize; i++) {
			pq.offer(new Element(map.get(i)[0], i, 0));
		}

		Element tem = null;
		int i = 1;
		while ((tem = pq.poll()) != null) {
			System.out.print(tem.value + "\t");
			if (i % 6 == 0)
				System.out.println();
			i++;
			// Put the next element to array if have
			if (tem.whichIndex + 1 < map.get(tem.whichArray).length)
				pq.offer(new Element( map.get(tem.whichArray)[tem.whichIndex + 1], tem.whichArray, tem.whichIndex + 1));
		}
	}

运行结果:
2	5	6	8	9	19	
20	24	31	38	67	76	
234	266	388	389	399	736	
736	1021	3923	7136	39342	


原理很简单: 先把每个数组的首元素取出来,形成一个堆结构。然后取出堆顶元素(目前的最小值),再将堆顶元素所在数组的后一个元素加入到堆中。如此循环直到所有元素被处理。

这个算法有个可以优化的地方,在从优先队列取出堆顶元素和重新加入元素这两步是可以合并的,没有合并的原因是java的PriorityQueue没有提供相应的接口。

附件是源码。
4
0
分享到:
评论

相关推荐

    高级java工程师面试考纲,java高级工程师进阶知识地图

    - **具体实现**:深入学习`ArrayList`(基于数组的列表实现)、`LinkedList`(双向链表实现)、`Vector`(线程安全的`ArrayList`)、`Stack`(基于`Vector`实现的后进先出队列)、`PriorityQueue`(基于优先级的...

    java语言集合框架

    最后,工具类如`Guava`和`Apache Commons Collections`提供了更多高级功能和优化的集合实现,如多路集、不可变集合、并行流等,它们可以进一步增强Java集合框架的功能。 总之,Java语言集合框架是Java编程的核心,...

    java-leetcode面试题解哈希表第352题将数据流变为多个不相交区间-题解.zip

    - 优先队列可以使用`PriorityQueue`,并且需要自定义比较器来保证区间按照结束位置排序。 - 在插入和删除区间时,需要考虑到区间合并的情况,确保不相交区间的特点。 总结,本题主要考察了哈希表、优先队列(最小堆...

    Java实现 LeetCode 632 最小区间(又是先序队列,官方给的是堆)

    给出的Java解决方案使用了优先队列(PriorityQueue)来辅助找到这个最小区间。首先,我们需要理解这个算法的思路: 1. **初始化**:创建一个大小为k的优先队列,并用一个自定义的比较器(Comparator)来比较队列中...

    ecs.rar_ecs_二叉树

    4. 排序和优先队列:堆排序和优先队列(如Java中的PriorityQueue)使用了二叉堆结构。 在“www.pudn.com.txt”和“二叉树”这两个文件中,可能会包含对二叉树更深入的解释,比如具体的实现代码、例子或者解题思路。...

    AlgorithmsII:算法,第二部分,普林斯顿大学,Coursera

    - **B树与B+树**:多路搜索树,常用于数据库和文件系统中。 5. **字符串处理**: - **KMP算法**:处理模式匹配问题,避免不必要的回溯。 - **Manacher's算法**:在线性时间内找到字符串中的最长回文子串。 - **...

    ProgrammingPearls

    此外,Java集合框架中的`PriorityQueue`可以用来实现优先级队列,这在多路归并过程中非常有用。 对于排序算法,快速排序和归并排序是两个常用的选择,但面对大数据时,通常会选择归并排序。归并排序的时间复杂度为O...

    Java开发技术大全 电子版

    11.2.3优先队列(PriorityQueue)使用示例340 11.2.4哈希集合(HashSet)使用示例343 11.2.5哈希映射类(HashMap)使用示例347 11.2.6有序树(TreeSet)使用示例349 11.2.7有序树映射类(TreeMap)使用示例353 ...

    数据结构

    5. 树:树结构包括二叉树、平衡二叉树(如AVL树、红黑树)和多路搜索树等。二叉树常用于查找和排序,平衡二叉树则保证了操作的效率。Java集合框架中没有直接提供树结构,但可以使用`java.util.TreeSet`或`java.util....

    百度持续交付项目组面试题

    快速排序是一种高效的排序算法,采用分治法策略来把一个序列分为较小和较大的两个子序列,然后递归地排序两个子序列。快速排序的关键在于选择合适的基准值进行分区。 **示例代码**: ```java public class ...

Global site tag (gtag.js) - Google Analytics