*文中内容大多来源于《数据结构 --Java语言描述》(第二版) 刘小晶 杜选 主编
*此系列文章作为学习记录,若文中内容有误,请大家指出,谢谢
优先级队列
优先级队列是一种带有优先级的队列,它是一种比栈和队列更为专有的数据结构,与普通队列一样,优先级队列中数据元素按关键字的值有序排列。由于很多情况下,需要访问具有最小关键字值的数据元素(例如要寻找最便宜的方法或最短的路径去做某件事),因袭,约定关键字最小的数据元素(或者在某些实现中是关键字最大的数据元素)具有最高的优先级,并且总是排在队首。
接口描述:
public interface IQueue {
public void clear();
public boolean isEmpty();
public int length();
public Object peek(); //取队首元素并返回其值
public void offer(Object x) throws Exception; //入队操作
public Object poll(); //出队操作
}
优先队列中结点data的类描述:
public class PriorityQData {
public Object elem; //结点的数据元素值
public int priority; //结点的优先数
public PriorityQData(Object elem, int priority){
this.elem = elem;
this.priority = priority;
}
}
实现IQueue接口的类描述:
import Book_U2.Node;
public class PriorityQueue implements IQueue {
private Node front; //队首的引用
private Node rear; //队尾的作用
//优先队列类的构造函数
public PriorityQueue(){
front = rear = null;
}
//队列置空
public void clear(){
front = rear = null;
}
//队列判空
public boolean isEmpty(){
return front == null;
}
//求队列长度
public int length(){
Node p = front;
int length = 0; //队列的长度
while(p != null){ //一直查找找到队尾
p = p.next;
++length; //长度增加1
}
return length;
}
//入队
public void offer(Object x){
PriorityQData pn = (PriorityQData)x;
Node s = new Node(pn); //构造一个新结点
if (front == null) //队列为空
front = rear = s; //修改队列的首尾结点
else{
Node p = front , q = front;
while(p != null && pn.priority >= ((PriorityQData)p.data).priority){ //新结点的数据域值与队列结点的数据域值相比较
q = p;
p = p.next;
}
if (p == null){ //p为空,表示遍历到了队列尾部
rear.next = s; //将新结点加入到队尾
rear = s; //修改队尾指针
}
else if (p == front){ //p的优先级大于队首结点的优先级
s.next = front; //将新结点加入到队首
front = s; //修改队首指针
}
else { //新结点加入队列中部
q.next = s;
s.next = p;
}
}
}
//读取队首元素
public Object peek(){
if (front == null) //队列为空
return null;
else //返回队首结点的数据域值
return front.data;
}
//出队
public Object poll(){
if (front == null) //队列为空
return null;
else{ //返回队首结点的数据域值,并修改队首指针
Node p = front;
front = p.next;
return p.data;
}
}
//输出所有队列中的所有数据元素(从队首到队尾)
public void display(){
if (!isEmpty()){
Node p = front;
while(p != rear.next){ //从队首到队尾
PriorityQData q = (PriorityQData)p.data;
System.out.println(q.elem + " " + q.priority);
p = p.next;
}
}
else
System.out.println("此队列为空");
}
}
Node的描述:
/**
* data是数据域,用来存放数据元素的值;next是指针域,用来存放后继结点的地址
*/
public class Node {
public Object data; //存放结点值
public Node next; //后继结点的引用
//无参数时的构造函数
public Node(){
this(null,null);
}
//带一个参数时的构造函数
public Node(Object data){
this(data,null);
}
//带两个参数时的构造函数
public Node(Object data,Node next){
this.data = data;
this.next = next;
}
}
并附上一个简易实例
- 设计一个程序模仿操作系统的进程管理问题。要求按进程服务优先级高的先服务、优先级相同的按先到先服务的原则进行管理。
- 操作系统中每个进程的模仿数据由进程号和进程优先级两部分组成,进程号是每个不同进程的唯一标识,优先级通常是一个0到40的数值,规定0为优先级最高,40为优先级最低。下面为一组模拟数据:
| 进程号 | 进程优先级 |
|1 | 20|
|2 | 40|
|3 | 0|
|4 | 10|
|5 | 40|
程序代码
package Book_U3;
public class Example3_6 {
public static void main(String[] args){
PriorityQueue pm = new PriorityQueue(); //构造一个对象
pm.offer(new PriorityQData(1, 20)); //插入优先级队列
pm.offer(new PriorityQData(2, 30));
pm.offer(new PriorityQData(3, 20));
pm.offer(new PriorityQData(4, 20));
pm.offer(new PriorityQData(5, 40));
pm.offer(new PriorityQData(6, 10));
System.out.println("进程服务的顺序:");
System.out.println("进程ID进程优先级");
while(!pm.isEmpty()){ //从队首到队尾,输出结点的数据域值和优先级
PriorityQData p = (PriorityQData)pm.poll(); //移除队首结点,并返回其数据域值
System.out.println(" " + p.elem + "\t" + p.priority); //输出
}
}
}