注:此文需要对有序二叉堆、优先队列等知识有所了解,建议看完用有序二叉堆实现优先队列后再阅读此文
背景
普通优先队列(不带索引)只能访问有序二叉堆的根节点,而无法引用队列中的其它任何元素。
特点
索引优先队列中存储的元素都有对应的“索引”,通过“索引”我们可以引用该索引对应的元素。可以理解为HashMap中的key-value,key即索引,value即所对应的元素。
实现要点
数组T[] a存放所有的元素,数组的下标对应该元素的索引,元素在该数组中是无序的。数组int[] pq 存放所有元素的索引,pq要实现为优先队列(即有序二叉堆的结构),索引在pq中是有序的数组int[] qp是pq的“倒置”数组,下标为元素的索引,若pq[i] = k,则pq[k] = i。默认情况下存放-1,此数组用来通过索引拿到在二叉堆(pq)中的节点位置。
代码实现
public class IndexMaxPQ<T extends Comparable<T>>{
private int N =
0;
private int index =
0;
private T[] a;
private int[] pq;
private int[] qp;
public IndexMaxPQ(
int size){
N = size;
for(
int i =
0; i < N; i++){
qp[i] = -
1;
}
a = (T[])
new Comparable<T>(N +
1);
pq =
new int[](N +
1);
qp =
new int[](N +
1);
}
public void insert(
int k, T item){
if (contains(k)) {
throw new IllegalArgumentException(
"index is already in the priority queue");
}
a[k] = item;
pq[++index] = k;
qp[k] = index;
swim(index);
}
public boolean contains(
int k){
return qp[k] != -
1;
}
public void delete(
int k){
int j = qp[k];
pq[j] = pq[index];
pq[index] =
null;
sink(j);
qp[k] = -
1;
a[k] =
null;
index--;
}
public T
delMax(){
T max = a[pq[
1]];
int k = pq[
1];
a[k] =
null;
pq[
1] = pq[index--];
sink(
1);
qp[k] = -
1;
return T;
}
private void swim(
int j){
while (j >
1) {
if (a[pq[j/
2]] < a[pq[j]]) {
swap(j/
2, j);
j = j /
2;
}
else{
break;
}
}
}
private void swap(
int m,
int n){
int iTemp = pq[m];
pq[m] = pq[n];
pq[n] = iTemp ;
qp[pq[m]] = m;
qp[pq[n]] = n;
}
private void sink(
int j){
while (j *
2 < N) {
int m = j *
2;
if (a[pq[m]] < a[pq[m++]]) {m++;}
if (a[pq[j]] > a[pq[m]]) {
break;}
swap(j, m);
j = m;
}
}
}