我写了这个方法来测试我的优先级队列,它的参数是一个ArrayList和一个Comparator:
@Test
public void testPriorityQueue_ExtractMax() {
PriorityQueue queue = new PriorityQueue(new IntegerComparator());
Integer[] arrayExp={14, 9};
queue.insert(16);
queue.insert(9);
queue.insert(14);
queue.extractMax();
assertArrayEquals(arrayExp, queue.getArray().toArray());
}
现在,如果我执行它,它说我的结果中的第一个元素是9,但我必须是14(队列的新根)。这些方法是提取最大值和 heapify 。我该如何解决?
public void heapify(int index) {
int largest = index;
int leftIndex = 2 * index + 1;
int rightIndex = 2 * index + 2;
if (leftIndex < queue.size() && c.compare(queue.get(index), (queue.get(leftIndex))) < 0)
largest = leftIndex;
if (rightIndex < queue.size() && c.compare(queue.get(largest), queue.get(rightIndex)) < 0)
largest = rightIndex;
if (largest != index) {
swap(index, largest);
heapify(largest);
}
}
public T extractMax() {
if (queue.size() == 0) return null;
T min = queue.get(0);
queue.remove(0);
queue.set(0, queue.get(queue.size() - 1));
heapify(0);
return min;
}
这是IntegerComparator:
public class IntegerComparator implements Comparator<Integer>{
@Override
public int compare(Integer l1, Integer l2) {
int result = l1.compareTo(l2);
if(result != 0)
return result;
return -1;
}
}
EDIT_2:这是我的插入方法,可能是问题所在:
public void insert(T elem) {
int i = queue.size();
int parentIndex = (i - 1) / 2;
while (i > 0 && c.compare(elem, queue.get(parentIndex)) == 1) {
queue.set(i, queue.get(parentIndex));
i = parentIndex;
parentIndex = (i - 1) / 2;
}
queue.add(i, elem);
}
答案 0 :(得分:1)
作为建议,考虑在索引0处添加一个未使用的元素,以便访问每个节点的父节点/子节点更直观。
示例强>:
考虑堆heap = [-1, 6, 4, 5, 2, 1, 4, 3]
,其中根定义为heap[1]
,堆的数据位于index = 1
到堆的大小。
要访问index
节点的子节点,可以直观地说左侧子节点定义为heap[2 * index]
,右侧子节点定义为heap[2 * index + 1]
。同样,要访问index
节点的父节点,可以使用int截断来访问父节点:
int parentInd = (int)(index/2);
T parent = heap[parentInd];
<强>解决方案强>:
正如raul1ro指出的那样,你正在丢失你不打算删除的索引0的数据。
在extractMax()
:
T min = queue.get(0);
queue.remove(0);
queue.set(0, queue.get(queue.size() - 1));
应该是:
T min = queue.get(0); //Get min
T temp = queue.get(queue.size() - 1); //Get the last element in heap as temp
queue.remove(queue.size - 1); //Remove the last element
queue.set(0, temp); //Set the root to the temp value so that you can heapify
这将使你在extractMax()
希望有所帮助!
答案 1 :(得分:1)
执行此操作时queue.remove(i);
会自动将索引i后的所有元素移至左侧一个位置。
https://www.tutorialspoint.com/java/util/arraylist_remove.htm
使用queue.set(0, queue.get(queue.size() - 1));
您只需在索引0上设置队列中最后一个索引的值,并从索引0中丢失值,但它仍然保留在最后一个位置。
阅读插入方法
在第一步queue.set(i, queue.get(parentIndex));
i = queue.size()
时,该平均索引不存在于队列中。