算法—优先队列

许多应用程序都需要处理有序的元素,但不一定要求它们全部有序,或是不一定要一次就将它们排序。很多情况下我们会收集一些元素,处理当前键值最大的元素,然后再收集更多的元素,再处理当前键值最大的元素,如此这般。

在这种情况下,一个合适的数据结构应该支持两种操作:删除最大元素和插入元素。这种数据类型叫做优先队列。优先队列的使用和队列(删除最老的元素)以及栈(删除最新的元素)类似,但高效地实现它则更有挑战性。

通过插入一列元素然后一个个地删掉其中最小的元素,我们可以用优先队列实现排序算法。一种名为堆排序的重要排序算法也来自于基于堆的优先队列的实现。

API

优先队列最重要的操作就是删除最大元素和插入元素,

优先队列的调用示例

为了展示优先队列的抽象模型的价值,考虑以下问题:输入N个字符串,每个字符串都对映着一个整数,你的任务就是从中找出最大的(或是最小的)M个整数(以及关联的字符串)。这些输入可能是金融事务,你需要从中找出最大的那些;或是农产品中的杀虫剂含量,这时你需要从中找出最小的那些;在某些应用场景中,输入量可能非常巨大,甚至可以认为输入是无限的。解决这个问题的一种方法是将输入排序然后从中找出M个最大的元素,但我们已经说明输入将会非常庞大。另一种方法是将每个新的输入和已知的M个最大元素比较,但除非M较小,否则这种比较的代价会非常高昂。只要我们能够高效地实现insert()和delMin(),下面的优先队列用例中调用了MinPQ的TopM就能使用优先队列解决这个问题。在现代基础性计算环境中超大的输入N非常常见,这些实现使我们能够解决以前缺乏足够资源去解决的问题。如表所示

算法:

/**
 * 一个优先队列的用例
 */
public class TopM {

	//打印输入流中最大的M行
	public static void main(String[] args) {
		int M = Integer.parseInt(args[0]);
		MinPQ<Transaction> pq = new MinPQ<Transaction>(M+1);
		//为下一行输入创建一个元素并放入优先队列中
		while(StdIn.hasNextLine()){
			pq.insert(new Transaction(StdIn.readLine()));
			if(pq.size() > M){
				pq.delMin();//如果优先队列中存在M+1个元素则删除其中最小的元素
			}	//最大的M个元素都在优先队列中

			Stack<Transaction> stack = new Stack<Transaction>();
			while(!pq.isEmpty()){
				stack.push(pq.delMin());
			}
			for (Transaction t : stack) {
				StdOut.println(t);
			}
		}
	}
}

这段代码调用了MinPQ并会打印数字最大的M行。

源码下载

时间: 2024-10-05 03:10:19

算法—优先队列的相关文章

Dijkstra算法优先队列实现与Bellman_Ford队列实现的理解

1 /* 2 Dijkstra算法用优先队列来实现,实现了每一条边最多遍历一次. 要知道,我们从队列头部找到的都是到 3 已经"建好树"的最短距离以及该节点编号, 并由该节点去更新 树根 到其他点(被更新的节点可以在队列中 4 ,也可以是非队列中的节点)的距离 . 5 6 ////队列中的节点都是要等待更新的节点 7 8 如果某个节点从队列中出来的时候,如果cur.first != dist[cur.second] 就是 cur.second这个节点一开始 9 被更新的最短距离值 和

算法-优先队列与堆排序

我们自己每天使用的电脑能同时运行多个应用程序,没有感觉到卡顿,电脑为每个应用程序的事件分配了一个优先级,移动端的手机也是,通常不管我们是在看电影,发短信只要有电话,电话绝对是优先级最高的.这个时候我们需要一种合理的数据结构删除最大元素和插入元素,我们可以称之为优先队列.实现这种优先队列最合适的数据结构可以通过经典的二叉堆来实现,相对于其他数据结构更高效. 优先队列 开始撸代码之前我们需要明白几个概念: 1.当一棵二叉树的每个节点都大于等于等于它的两个子节点时,它称之为堆有序. 2.二叉堆是一组能

《编程珠玑》

第1章 开篇 问题: 输入: 一个最多包含n个正整数的文件,每个数都小于n,其中n=107.如果在输入文件中有任何整数重复出现就是致命错误.没有其它数据与该整数相关联. 输出: 按升序排列的输入整数的列表. 约束: 最多有(大约)1MB的内存空间可用,有充足的磁盘存储空间可用.运行时间最多几分钟,运行时间10秒就不需要进一步优化了. 解决方案: 位向量     //phase 1:initialize set to empty         for i = [0,n)            

DS课设【坦克大战最短路】(MummyDing)

DS课设[坦克大战最短路] 还是决定写点东西简单记录下这次编码. 一.想法 还没放假的时候只想着用C#实现,算法图论方面觉得图论方向会靠谱些,但一直没有什么好点子.C#以前也没学过,自信来源于MFC的学习经历(以前也是用它做了C语言课设).C#应该是没有MFC那么复杂的,心想看几天应该就可以上手一些小东西了,事实证明也如此. 寒假时间相对以前更长,也并不着急做课设.开始一段是刷题+学习Kinect+顺带了解Kinect,后来在刷题过程中遇到这题,还蛮有意思的,当即就写了个"坦克大战最短路简单设计

CF449B最短路

B. Jzzhu and Cities Jzzhu is the president of country A. There are n cities numbered from 1 to n in his country. City 1 is the capital of A. Also there are mroads connecting the cities. One can go from city ui to vi (and vise versa) using the i-th ro

POJ 3159 Candies、

题意:n个小孩,m个比较(给你两个孩子代号a,b.然后c意味着a比b最多只能少c个糖果),问1和n之间差距最大的糖果数量. 思路:这是一个差分约束思路 不懂得:传送门, 转化一下就是一个SPFA求最短路的问题了. 参照了kuangbin大神的模板. 1 #include<cstring> 2 #include<cmath> 3 #include<cstdio> 4 const int qq=30005; 5 const int MAX=0x3f3f3f3f; 6 int

POJ-3253 Fence Repair---Huffman贪心

题目链接: https://vjudge.net/problem/POJ-3253 题目大意: 有一个农夫要把一个木板钜成几块给定长度的小木板,每次锯都要收取一定费用,这个费用就是当前锯的这个木版的长度 给定各个要求的小木板的长度,及小木板的个数n,求最小费用 思路: HUffman算法 优先队列 1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring>

【坐在马桶上看算法】算法12:堆——神奇的优先队列(下)

接着上一Pa说.就是如何建立这个堆呢.可以从空的堆开始,然后依次往堆中插入每一个元素,直到所有数都被插入(转移到堆中为止).因为插入第i个元素的所用的时间是O(log i),所以插入所有元素的整体时间复杂度是O(NlogN),代码如下. n=0; for(i=1;i<=m;i++) {     n++;     h[ n]=a[ i];  //或者写成scanf("%d",&h[ n]);     siftup(); } 其实我们还有更快得方法来建立堆.它是这样的. 直接

【坐在马桶上看算法】算法11:堆——神奇的优先队列(上)

堆是什么?是一种特殊的完全二叉树,就像下面这棵树一样. 有没有发现这棵二叉树有一个特点,就是所有父结点都比子结点要小(注意:圆圈里面的数是值,圆圈上面的数是这个结点的编号,此规定仅适用于本节).符合这样特点的完全二叉树我们称为最小堆.反之,如果所有父结点都比子结点要大,这样的完全二叉树称为最大堆.那这一特性究竟有什么用呢? 假如有14个数分别是99.5.36.7.22.17.46.12.2.19.25.28.1和92.请找出这14个数中最小的数,请问怎么办呢?最简单的方法就是将这14个数从头到尾