《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅰ
许多应用程序都需要处理有序的元素,但不一定要求他们全部有序,或者是不一定要以此就将他们排序。很多情况下我们会手机一些元素,处理当前键值最大的元素,然后再收集更多的元素,再处理当前键值最大的元素。如此这般。
在这种情况下,一个合适的数据结构应该支持两种操作:删除最大元素和插入元素。这种数据类型叫做优先队列(priority queue)。优先队列的使用和队列(删除最老的元素)以及栈(删除最新的元素)类似,但高效地实现该数据结构有一定的困难。
下文将简单的讨论优先队列的基本表现形式(其一或者两种操作都能在线性时间完成)。
2.4.1 API
优先队列是一种抽象数据类型(是一种能够对使用者隐藏数据表示的数据类型),它表示了一组值和对这些值的操作,它的抽象层使我们能够方便地将应用程序和我们学习的各种具体实现隔离开来。优先队列最重要的操作就是删除最大元素和插入元素,所以我们会把精力集中在它们身上。删除最大元素的方法名为delMax(),插入元素的方法名为insert()。通过less()来比较两个元素。如果允许重复元素,最大表示的是所有最大元素之一。为了将API定义完整,我们还需要加入构造函数和一个空队列测试方法。为了保证灵活性,我们在实现中使用了泛型,将实现Comparable接口的数据的类型作为参数Key。这使得我们可以不必再区别元素和元素的键,对数据类型和算法的描述也将更加清晰和简洁。
public class MaxPQ<Key extends Comparable<Key>> | |
MaxPQ() MaxPQ(int max) MaxPQ(Key[] a) void Insert(Key v) Key max() Key delMax() boolean isEmpty() int size() |
创建一个优先队列 创建一个初始容量为max的优先队列 用a[]中的元素创建一个优先队列 向优先队列中插入一个元素 返回最大元素 删除最大元素 返回队列是否为空 返回优先队列中的元素个数 |
表2.4.1 泛型优先队列的API
为了用例代码的方便,API包含的三个构造函数使得用例可以构造指定大小的优先队列(还可以用给定的一个数组将其初始化)。为了使用例代码更加清晰,我们会在适当的地方使用另一个类MinPQ。它和MaxPQ类似,只是含有一个delMin()方法来删除并返回队列中键值最小的那个元素。MaxPQ的任意实现都能很容易地转化为MinPQ的实现,反之亦然,只需要改变一下less()比较的方向即可。
优先队列的调用示例
考虑一下问题:输入N个字符串,每个字符串都对映着一个整数,你的任务就是从中找出最大的(或是最小的)M个整数(及其最小的)M个整数(及其关联的字符串)。解决这个问题的一种方法是将输入排序然后从中找出M个最大元素,但输入会非常庞大。另一种方法是将每个新的输入和已知的M个最大元素比较,但除非M较小,否则这种比较的代价会非常昂贵。只要我们能够高效地实现insert()和delMin(),下面的优先队列用例中调用了MinPQ的TopM就能使用优先队列解决这个问题,这就是目标。
示例 | 时间 | 空间 |
排序算法的用例 | NlogN |
N |
调用初级实现的优先队列 | NM |
M |
调用基于堆排序的优先队列 | NlogM |
M |
表2.4.2 N个输入中找到最大的M个元素成本
一个优先队列的用法
public class TopM { // This class should not be instantiated.
private TopM() { } /**
* Reads a sequence of transactions from standard input; takes a
* command-line integer M; prints to standard output the M largest
* transactions in descending order.
*/
public static void main(String[] args) {
int M = Integer.parseInt(args[0]);
MinPQ<Transaction> pq = new MinPQ<Transaction>(M+1); while (StdIn.hasNextLine()) {
// Create an entry from the next line and put on the PQ.
String line = StdIn.readLine();
Transaction transaction = new Transaction(line);
pq.insert(transaction); // remove minimum if M+1 entries on the PQ
if (pq.size() > M)
pq.delMin();
} // top M entries are on the PQ // print entries on PQ in reverse order
Stack<Transaction> stack = new Stack<Transaction>();
for (Transaction transaction : pq)
stack.push(transaction);
for (Transaction transaction : stack)
StdOut.println(transaction);
}
}
从命令行输入一个整数M从输入流获得一系列字符串,输入流的每一行表示一个交易。这段代码调用了MinPQ并会打印数字最大的M行。它用到了Transaction类,构造了一个用数字作为键的优先队列。当优先队列的大小超过M时就删掉其中最小的元素。处理完所有交易,优先队列中存放着以曾旭排列的最大的M个交易,然后这段代码将他们放到一个栈中,遍历这个栈以点到他们的顺序,从而将他们按降序打印出来。
《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅰ的更多相关文章
- 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅶ(延伸:堆排序的实现)
2.4.5 堆排序 我们可以把任意优先队列变成一种排序方法.将所有元素插入一个查找最小元素的有限队列,然后再重复调用删除最小元素的操作来将他们按顺序删去.用无序数组实现的优先队列这么做相当于进行一次插 ...
- 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅵ
· 学后心得体会与部分习题实现 心得体会: 曾经只是了解了优先队列的基本性质,并会调用C++ STL库中的priority_queue以及 java.util.PriorityQueue<E&g ...
- 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅴ
命题Q.对于一个含有N个元素的基于堆叠优先队列,插入元素操作只需要不超过(lgN + 1)次比较,删除最大元素的操作需要不超过2lgN次比较. 证明.由命题P可知,两种操作都需要在根节点和堆底之间移动 ...
- 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅳ
2.4.4 堆的算法 我们用长度为 N + 1的私有数组pq[]来表示一个大小为N的堆,我们不会使用pq[0],堆元素放在pq[1]至pq[N]中.在排序算法中,我们只能通过私有辅助函数less()和 ...
- 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅲ
2.4.3 堆的定义 数据结构二叉堆能够很好地实现优先队列的基本操作.在二叉堆的数组中,每个元素都要保证大于等于另两个特定位置的元素.相应地,这些位置的元素又至少要大于等于数组中的两个元素,以此类推. ...
- 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅱ
2.4.2初级实现 我们知道,基础数据结构是实现优先队列的起点.我们可以是使用有序或无序的数组或链表.在队列较小时,大量使用两种主要操作之一时,或是所操作元素的顺序已知时,它们十分有用.因为这些实现相 ...
- C++Primer 4th edition读书笔记-第二章
1 变量的定义用于为变量分配存储空间,还可以为变量指定初始值.在一个程序中,变量有且只有一个定义.声明用于向程序表明变量的名字和类型.定义也是声明:当定义变量时,我们声明了它的类型和名字.可以通过使用 ...
- 《Algorithms 4th Edition》读书笔记——3.1 符号表(Elementary Symbol Tables)-Ⅳ
3.1.4 无序链表中的顺序查找 符号表中使用的数据结构的一个简单选择是链表,每个结点存储一个键值对,如以下代码所示.get()的实现即为遍历链表,用equals()方法比较需被查找的键和每个节点中的 ...
- 《C++ Primer 4th》读书笔记 序
注:本系列读书笔记是博主写作于两三年前的,所以是基于<C++ Primer>第四版的,目前该书已更新至第五版,第五版是基于C++11标准的,貌似更新挺多的.博主今年应届硕士毕业,如若过阵子 ...
随机推荐
- (转)iOS Wow体验 - 第三章 - 用户体验的差异化策略
本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第三章译文精选,其余章节将陆续放出.上一篇:Wow ...
- HDOJ 1316 How Many Fibs?
JAVA大数.... How Many Fibs? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Jav ...
- Qt5官方demo解析集21——Extending QML - Adding Types Example
本系列全部文章能够在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 又是一个新的系列了,只是这个系列和我们之前的Chapt ...
- 使用android-resource-remover删除项目中无用的资源,减少包的大小
写这篇文章的原因是,一个CSDN的资源链接,Android程序员必备精品资源,在该链接的实用工具集锦中有一个工具吸引了我的注意,那就是android-resource-remover,它的解释是:一个 ...
- 解决android自带textview右侧文字不能对齐的问题
package com.sixin.view; import android.content.Context; import android.graphics.Canvas; import andro ...
- CentOS6.6(单用户模式)重设root密码
1.开机时手要快按任意键,因为默认时间5s 2.grub菜单,只有一个内核,没什么好上下选的,按e键.不过如果你升级了系统或安装了Xen虚拟化后,就会有多个显示了. 3.接下来显示如下,选择第二项,按 ...
- HTML与CSS入门——第十二章 在网页中使用多媒体
知识点: 1.如何链接多媒体文件 2.如何嵌入多媒体文件 3.使用多媒体的更多技巧 多媒体文件:音频,视频和动画,以及静态的图像和文本. 这里我就直接讲HTML5了…… 此前都是用ojbect来加载或 ...
- Chinese_PRC_CI_AS and SQL_Latin1_General_CP1_CI_AS类型错误
在编写存储过程时,经常会用到临时表,而且往往会使用临时表与正式表相关联. 当临时表与正式表关联的字段是字符类型的时候,因为临时表创建的字符类型会默认数据库的编码,而正式表的字符编码可能不同,那么这个时 ...
- 如何制作windows服务安装包
以下转自:http://blog.csdn.net/chainan1988/article/details/7087006 Window服务的安装有两个方式: 一.命令安装 通过命令 ...
- Struts2.3.16.3 基本9个jar包
实践证明,Struts2.3.16.3 至少要下面9个Jar包才能正常启动. commons-fileupload-1.3.1.jar commons-logging-1.1.3.jar freema ...