在很多应用中,允许用例引用已经进入优先队列中的元素是有必要的。做到这一点的一种简单方法是给每个元素一个索引。
索引优先队列的API
API | 功能 |
---|---|
IndexMinPQ(int maxN) | 创建一个最大容量为maxN的优先队列,索引的取值范围为0至maxN-1 |
void insert(int i, Key key) | 插入一个元素,将它和索引i相关联 |
void change(int i, Key key) | 将索引为i的元素设为key |
boolean contains(int i) | 是否存在索引为i的元素 |
int delMin() | 删除最小元素并返回它的索引 |
boolean isEmpty() | 优先队列是否为空 |
int size() | 优先队列中的元素数量 |
void delete(int k) | 删除索引k及其相关联的元素 |
Key min() | 返回最小元素 |
int minIndex() | 返回最小元素的索引 |
这里只实现了部分API,完整的实现在这里。
package section4_4;
public class IndexMinPQ<Key extends Comparable<Key>> {
private int maxN;
private int n;
private int[] pq; //索引从1开始的堆,用于存放索引,pq[i] = n表示索引为i的元素为n
private int[] qp; //pq的逆,用于存放索引的索引,qp[n] = i表示元素n的索引为i
private Key[] keys; //keys[i]为i的优先级,用于存放元素
public IndexMinPQ(int maxN) {
this.maxN = maxN;
n = 0;
keys = (Key[]) new Comparable[maxN + 1];
pq = new int[maxN + 1];
qp = new int[maxN + 1];
for (int i = 0;i <= maxN;i++) {
qp[i] = -1;
}
}
public boolean isEmpty() {
return n == 0;
}
public boolean contains(int i) {
return qp[i] != -1;
}
public int size() {
return n;
}
private boolean greater(int i, int j) {
return keys[pq[i]].compareTo(keys[pq[j]]) > 0;
}
private void exch(int i, int j) {
int swap = pq[i];
pq[i] = pq[j];
pq[j] = swap;
qp[pq[i]] = i;
qp[pq[j]] = j;
}
//根结点的元素最小
private void swim(int k) {
while (k > 1 && greater(k/2,k)) {
exch(k,k/2);
k = k/2;
}
}
private void sink(int k) {
while (2*k <= n) {
int j = 2*k;
if (j < n && greater(j,j+1)) j++;
if (!greater(k,j)) break;
exch(k,j);
k = j;
}
}
public void insert(int i, Key key) {
n++;
qp[i] = n;
pq[n] = i;
keys[i] = key;
swim(n);
}
public int delMin() {
int min = pq[1];
exch(1,n--);
sink(1);
qp[min] = -1;
keys[min] = null;
pq[n+1] = -1;
return min;
}
public void change(int i, Key key) {
changeKey(i,key);
}
public void changeKey(int i, Key key) {
keys[i] = key;
swim(qp[i]);
sink(qp[i]);
}
}