所以我正在为我的班级做一个实验室。我需要使用数组列表在Java中创建Priority Queue。踢球者是每个节点必须有一个“句柄”,它只是一个对象,它包含与之关联的节点的索引。我知道这听起来很奇怪,但我们必须以这种方式实现它。无论如何,我的优先级队列似乎工作正常,除了句柄值显然没有正确更新,因为我没有通过句柄测试。另外,我在调用extractMin()之后才遇到句柄问题,所以我认为问题会出现在那个方法的某个地方,但我已经经历了一百万次这对我来说很好看。
这是我的优先队列类:
package lab3;
import java.util.ArrayList;
/**
* A priority queue class supporting operations needed for
* Dijkstra's algorithm.
*/
class PriorityQueue<T> {
final static int INF = 1000000000;
ArrayList<PQNode<T>> queue;
/**
* Constructor
*/
public PriorityQueue() {
queue = new ArrayList<PQNode<T>>();
}
/**
* @return true iff the queue is empty.
*/
public boolean isEmpty() {
if (queue.size() <= 0)
return true;
return false;
}
/**
* Insert a (key, value) pair into the queue.
*
* @return a Handle to this pair so that we can find it later.
*/
Handle insert(int key, T value) {
queue.add(new PQNode(key, value));
int loc = queue.size()-1;
// Swap with parent until parent not larger
while (loc > 0 && queue.get(loc).getKey() < queue.get(parent(loc)).getKey()) {
swap(loc, parent(loc));
loc = parent(loc);
}
return new Handle(loc);
}
private void swap(int i, int j) {
PQNode t = queue.get(i);
queue.set(i, queue.get(j));
queue.get(i).setHandleIndex(i);
queue.set(j, t);
queue.get(j).setHandleIndex(j);
}
/**
* @return the min key in the queue.
*/
public int min() {
if (isEmpty())
return -INF;
return queue.get(0).getKey();
}
/**
* Find and remove the smallest (key, value) pair in the queue.
*
* @return the value associated with the smallest key
*/
public T extractMin() {
if (isEmpty())
return null;
else{
T value = queue.get(0).getValue();
swap(0, queue.size()-1);
queue.get(queue.size()-1).setHandleIndex(-1);
queue.remove(queue.size()-1);
heapify(0);
return value;
}
}
private void heapify(int i) {
int left = leftChild(i);
int right = rightChild(i);
int min;
if (left <= queue.size()-1 && queue.get(left).getKey() < queue.get(i).getKey())
min = left;
else
min = i;
if (right <= queue.size()-1 && queue.get(right).getKey() < queue.get(min).getKey())
min = right;
if (min != i){
swap(i, min);
heapify(min);
}
}
private static int parent(int i) {
return (i-1)/2;
}
private static int leftChild(int i) {
return 2*i + 1;
}
/**
* @return the key associated with the Handle.
*/
public int handleGetKey(Handle h) {
if (h.getIndex() >= 0)
return queue.get(h.getIndex()).getKey();
return -INF;
}
/**
* Decrease the key to the newKey associated with the Handle.
*
* If the pair is no longer in the queue, or if its key <= newKey,
* do nothing and return false. Otherwise, replace the key with newkey,
* fix the ordering of the queue, and return true.
*
* @return true if we decreased the key, false otherwise.
*/
public boolean decreaseKey(Handle h, int newKey){
if (h.getIndex() == -1) //negative 1 is my signal for an invalidated handle
return false;
if (newKey > queue.get(h.getIndex()).getKey())
return false;
queue.get(h.getIndex()).setKey(newKey); // set the new key
correct(h.index); // restore the min-heap property
return true;
}
public void correct(int i)
{
{
while (i > 0 && queue.get(parent(i)).getKey() > queue.get(i).getKey()) {
swap(i, parent(i));
i = parent(i);
}
}
}
/**
* Return the index of the right child of node i.
* @param i index of parent
* @return the index of the right child of node i
*/
private static int rightChild(int i) {
return 2*i + 2;
}
/**
* @return the value associated with the Handle.
*/
public T handleGetValue(Handle h) {
if (h.getIndex() >= 0){
return queue.get(h.getIndex()).getValue();}
else{
return null;
}
}
我的PQNode课程:
package lab3;
public class PQNode<T> {
int key;
T value;
Handle handle;
PQNode(int k, T v){
key = k;
value = v;
handle = new Handle(0);
}
/**
* @return the key
*/
public int getKey() {
return key;
}
/**
* @param key the key to set
*/
public void setKey(int key) {
this.key = key;
}
/**
* @return the value
*/
public T getValue() {
return value;
}
/**
* @param value the value to set
*/
public void setValue(T value) {
this.value = value;
}
public void setHandle(Handle handle){
this.handle = handle;
}
/**
* @return the handle
*/
public Handle getHandle() {
return handle;
}
public int getHandleIndex(){
return handle.getIndex();
}
public void setHandleIndex(int i){
handle.setIndex(i);
}
}
我的手柄类:
package lab3;
public class Handle {
int index;
public Handle(int i) {
index = i;
}
/**
* @return the index
*/
public int getIndex() {
return index;
}
/**
* @param index the index to set
*/
public void setIndex(int index) {
this.index = index;
}
}
因为这是学校的工作,我会很感激提示,但尽量不要脱口而出。另外,如果您愿意,我也可以发布测试,但我不知道这是否会带来很多好处。只知道队列应该按原样运行,但是在使用extractMin()之后句柄不指向正确的节点。如果您想了解更多信息,请告诉我,我知道这有点模糊。非常感谢你们。
编辑:这是我失败的特殊测试
public void basicHandleAndDecreaseTest() {
PriorityQueue<String> q = new PriorityQueue<String>();
Map<String, Handle> valuesToHandles = new HashMap<String, Handle>();
Map<String, Integer> valuesToKeys = new HashMap<String, Integer>();
int seq = 0;
// Generate random numbres for the keys.
for (int i = 0; i < 20; i++) {
int key = RAND.nextInt(100);
String val = Integer.toString(seq); // guarantees that the value is unique.
seq++;
valuesToKeys.put(val, key);
}
// Keep track of handles and build queue.
for (Map.Entry<String, Integer> entry : valuesToKeys.entrySet()) {
int key = entry.getValue();
String value = entry.getKey();
Handle h = q.insert(key, value);
assertEquals(key, q.handleGetKey(h));
assertEquals(value, q.handleGetValue(h));
valuesToHandles.put(value, h);
}
// Remove some of the elements.
for (int i = 0; i < 5; i++) {
String val = q.extractMin();
valuesToKeys.remove(val);
valuesToHandles.remove(val);
}
// Make sure the handles are still valid.
for (Map.Entry<String, Integer> entry : valuesToKeys.entrySet()) {
int key = entry.getValue();
String value = entry.getKey();
Handle h = valuesToHandles.get(value);
assertEquals(value, q.handleGetValue(h)); <--Here is when I fail
}
// Add some more elements.
int limit = seq + 5;
for (int i = seq; i < limit; i++) {
int key = RAND.nextInt(100);
String val = Integer.toString(seq);
seq++;
valuesToKeys.put(val, key);
Handle h = q.insert(key, val);
valuesToHandles.put(val, h);
}
// Decrease keys unnecessarily and verify that they still work.
for (Map.Entry<String, Integer> entry : valuesToKeys.entrySet()) {
int key = entry.getValue();
String value = entry.getKey();
Handle h = valuesToHandles.get(value);
q.decreaseKey(h, key + 1);
assertEquals(key, q.handleGetKey(h));
assertEquals(value, q.handleGetValue(h));
}
// Change keys randomly, and check that the values remain attached to handles.
for (Map.Entry<String, Integer> entry : valuesToKeys.entrySet()) {
int key = entry.getValue();
String value = entry.getKey();
Handle h = valuesToHandles.get(value);
int newKey = RAND.nextInt(100);
q.decreaseKey(h, newKey);
if (newKey < key) {
assertEquals(newKey, q.handleGetKey(h));
} else {
assertEquals(key, q.handleGetKey(h));
}
assertEquals(value, q.handleGetValue(h));
}
}
答案 0 :(得分:0)
如果没有脱口而出,插入时返回的句柄应该是刚刚插入的节点的句柄,而不是新节点。这样,当你进行交换时它会得到更新。节点的句柄也需要初始化为比零更相关的东西。
这会让你接下来的错误...... :
测试程序中的一个错误,标记为“不必要地减少密钥并验证它们是否仍然有效”。正在测试错误的“密钥”值。节点中的密钥已更改为key+1,
,因此应该进行测试,而不是key.
这同样适用于标记为“随机更改密钥,并检查值是否仍附加到句柄”的块,只有这次新密钥是随机的,而不是key+1.
或
decreaseKey()
的意思使我失望。