首页 > 代码库 > 初步学习PriorityQueue

初步学习PriorityQueue

今天终于决定使用STL提供的priority_queue,发现还挺好用,虽然很多人都称他效率不够高,但是使用起来很方便。下面就总结一下它的一般用法:

模板原型:

priority_queue<T,Sequence,Compare>

T:存放容器的元素类型

Sequence:实现优先级队列的底层容器,默认是vector<T>

Compare:用于实现优先级的比较函数,默认是functional中的less<T>

常用的操作如下:

 

empty() 如果优先队列为空,则返回真
pop() 删除第一个元素
push() 加入一个元素
size() 返回优先队列中拥有的元素的个数
top() 返回优先队列中有最高优先级的元素

 

但是在使用时必须注意:priority_queue放置元素时,不会判断元素是否重复。(因为在模板的第二个参数时顺序容器,不能保证元素的唯一性)

下面例子是用Priority Queue保存学生信息,学生类含有姓名和成绩,当把学生保存在Priority Queue里时,成绩最低的学生放在最前面。如果想把成绩最高的放在最前面,只要把compare方法改成 return s2.grade - s1.grade; 即可。

 

 1 import java.util.Comparator;
 2 import java.util.PriorityQueue;
 3 import java.util.Random;
 4 
 5 public class PriorityQueueTutorial{
 6     
 7     public static void main(String args[]){
 8         PriorityQueue<Student> queue = new PriorityQueue<Student>(11,
 9                 new Comparator<Student>() {
10                   public int compare(Student s1, Student s2) {
11                     return s1.grade - s2.grade;
12                   }
13                 });        
14             
15         for (int i = 1; i <= 100; i++) {
16             queue.add(new Student("s" + i, (new Random().nextInt(1000))));
17         }
18         while (!queue.isEmpty()) {
19               System.out.println(queue.poll().toString());
20         }
21     }
22 }
23 
24 class Student {    
25     String name;
26     int grade;
27     public Student(String name, int grade)
28     {
29         this.name = name;
30         this.grade = grade;
31     }
32     
33     public String toString() {
34         return name + " " + grade;
35     }
36 }

 

在自己实现Compare函数(函数对象)时,函数对象是中的参数如果是const类型,那么队列存放的元素(比如Node)的比较函数也一定要实现为const。因为函数对象在执行时通过其参数调用Node的比较函数。

 

----------------------------------------------

我们知道队列是遵循先进先出(First-In-First-Out)模式的,但有些时候需要在队列中基于优先级处理对象。举个例子,比方说我们有一个每日交易时段生成股票报告的应用程序,需要处理大量数据并且花费很多处理时间。客户向这个应用程序发送请求时,实际上就进入了队列。我们需要首先处理优先客户再处理普通用户。在这种情况下,Java的PriorityQueue(优先队列)会很有帮助。 

PriorityQueue类在Java1.5中引入并作为 Java Collections Framework 的一部分。PriorityQueue是基于优先堆的一个无界队列,这个优先队列中的元素可以默认自然排序或者通过提供的Comparator(比较器)在队列实例化的时排序。

优先队列不允许空值,而且不支持non-comparable(不可比较)的对象,比如用户自定义的类。优先队列要求使用Java Comparable和Comparator接口给对象排序,并且在排序时会按照优先级处理其中的元素。 

优先队列的头是基于自然排序或者Comparator排序的最小元素。如果有多个对象拥有同样的排序,那么就可能随机地取其中任意一个。当我们获取队列时,返回队列的头对象。 

优先队列的大小是不受限制的,但在创建时可以指定初始大小。当我们向优先队列增加元素的时候,队列大小会自动增加。 

PriorityQueue是非线程安全的,所以Java提供了PriorityBlockingQueue(实现BlockingQueue接口)用于Java多线程环境。

PriorityQueue这种数据结构支持按照优先级取出里面的元素。这是和其它常用数据结构,比如 ArrayList, Queue, Stack等最大的区别。因为要支持优先级,而heap具有类似的结构,所以,PriorityQueue一般都是基于HEAP实现的。(也可以用其它数据结构实现,但是各种复杂度会有不同。)

-------------------------------------------------------------------------

基于HEAP实现的PriorityQueue复杂度分析:

add(E e): O(lg n)

poll():  O(lg n) (注意,取出元素只需要O(1), 但是维护HEAP结构需要 O(lg n))

remove(E e): O(n)