一、优先级队列
-
优先级队列是零个或多个元素的集合,每个元素都有一个优先级;
-
优先级队列:在入队列时,给每个元素都分配一个数字来标记其优先级,假设数字越小,对应元素的优先级越高,这样就可以在一个元素集合中访问优先级最高的元素并对其进行查找和删除操作。
-
对优先级队列执行的操作有
- 插入(入队)
- 出队(删除优先级最高的元素)
- 删除 (指定优先级的元素)
- 查找(指定优先级的元素)
- 查找队首的元素(拿到优先级最高的元素)
二、实现一个链式优先级队列
这里就是单链表的实现及其常用方法,请点击单链表常用方法、单链表相关面试真题
- 数据结构
class PrioQueue<E> {
class Entry<E> {
E data;
int prio; //优先级
Entry<E> next;
public Entry() {
this.data = null;
this.prio = -1;
this.next = null;
}
public Entry(E val,int prio) {
this.data = val;
this.prio = prio;
this.next = null;
}
}
private Entry<E> head;
public PrioQueue() {
this.head = new Entry<>();
}
}
- 基本操作
代码间的注释挺详细的,前面就不再解释啦
- 插入
//插入
public void insert(E val,int prio) {
Entry<E> entry = new Entry<>(val,prio);
Entry<E> cur = this.head;
while (cur.next != null) { //找到优先级比entry大的结点 cur.next
if (cur.next.prio > prio) {
break;
}
cur = cur.next;
}
entry.next = cur.next; //将entry插在它之前即cur之后的位置
cur.next = entry;
}
- 出队
//出队
public boolean delete() {
if (this.head.next == null) {
throw new UnsupportedOperationException("空队列,无法出队");
} else {
this.head.next = this.head.next.next; //删除头结点之后的第一个数据节点
return true;
}
}
- 删除某个优先级的(第一个)元素
//删除某个优先级的(第一个)元素
public void delete(int prio) {
Entry<E> cur = this.head;
while (cur.next != null) {
if (cur.next.prio < prio) {
cur = cur.next; //当cur.next.prio < prio时,cur接着向后遍历
} else if (cur.next.prio == prio) {
break; //当找到与优先级与prio相等的元素时,跳出循环
} else { //此时cur.next.prio > prio,说明没有找到优先级为prio的元素
throw new UnsupportedOperationException("未找到该优先级的元素,删除失败");
}
}
//cur.next是需要删除的结点,cur是待删除结点的前驱
// 只需让cur.next = cur.next.next就完成了对cur.next的删除
cur.next = cur.next.next;
}
- 获取某个优先级的(第一个)元素
//获取某个优先级的(第一个)元素
public E getPrio(int prio) {
Entry<E> cur = this.head.next;
while (cur != null) {
if (cur.prio < prio) { //当cur.next.prio < prio时,cur接着向后遍历
cur = cur.next;
} else if (cur.prio == prio) {
break; //当找到与优先级与prio相等的元素时,跳出循环
} else { //此时cur.next.prio > prio,说明没有找到优先级为prio的元素
throw new UnsupportedOperationException("未找到该优先级的元素");
}
}
return cur.data; //到这里就说明找到了优先级为prio的元素cur,返回cur.data
}
- 得到队首的元素:这里拿到的是优先级最高的元素
//得到队首的元素
public E getTop() {
if (this.head.next == null) {
throw new UnsupportedOperationException("空队列,队首元素不存在");
}
return this.head.next.data; //返回头结点之后的第一个数据节点
}
- 打印优先级队列
//打印优先级队列
public void show() {
Entry<E> cur = this.head.next;
while (cur != null) {
//这里打印元素以及它的优先级,比较直观
System.out.print(cur.data + "的优先级为:" + cur.prio + " ");
cur = cur.next;
}
System.out.println();
}