我一直在尝试编写一个递归方法,在元素入队时重塑堆数据结构,但我无法使其正常工作。我现在已经玩了4天而没有运气,所以我希望有人可以给我一些指导。我能够得到一个完美的递归reheapDown方法,所以我不知道为什么这个方法不会起作用。这是我正在研究的课程,其中包括reheapUp的迭代版本,我将其用作设计递归版本的模板:
public class Heap<T extends Comparable<T>> implements PriQueueInterface<T>
{
private ArrayList<T> elements; // priority queue elements
private int lastIndex; // index of last element in priority queue
private int maxIndex; // index of last position in ArrayList
public Heap(int maxSize)
{
elements = new ArrayList<T>(maxSize);
lastIndex = -1;
maxIndex = maxSize - 1;
}
public boolean isEmpty()
// Returns true if this priority queue is empty; otherwise, returns false.
{
return (lastIndex == -1);
}
public boolean isFull()
// Returns true if this priority queue is full; otherwise, returns false.
{
return (lastIndex == maxIndex);
}
private void reheapUp(T element)
// Current lastIndex position is empty.
// Inserts element into the tree and ensures shape and order properties.
{
int hole = lastIndex;
while ((hole > 0) // hole is not root and element > hole's parent
&&
(element.compareTo(elements.get((hole - 1) / 2)) > 0))
{
// move hole's parent down and then move hole up
elements.set(hole,elements.get((hole - 1) / 2));
hole = (hole - 1) / 2;
}
elements.set(hole, element); // place element into final hole
}
private void recReheapUp(T element)
{
int hole = lastIndex;
//hole is not root and element > hole's parent
if (hole > 0)
{
if (element.compareTo(elements.get((hole - 1) / 2)) > 0)
{
elements.set(hole,elements.get((hole - 1) / 2));
hole = (hole - 1) / 2;
}
}
//base condition
if (hole == 0 && element.compareTo(elements.get((hole - 1) / 2)) <= 0))
{
elements.set(hole, element); // place element into final hole
return;
}
recReheapUp(element);
}
public void enqueue(T element) throws PriQOverflowException
// Throws PriQOverflowException if this priority queue is full;
// otherwise, adds element to this priority queue.
{
if (lastIndex == maxIndex)
throw new PriQOverflowException("Priority queue is full");
else
{
lastIndex++;
elements.add(lastIndex,element);
recReheapUp(element);
}
}
每当项目入队时,都会调用reheapUp()
和recReheapUp()
方法。我已经多次重复使用recReheapUp()
方法,甚至不值得发布我尝试过的所有更改。
我会说我认为问题在于我的基本情况,尽管在一般情况下也可能存在逻辑缺陷。
无论我做什么,我都会遇到堆栈溢出错误,这告诉我递归方法没有正确终止。我刚刚切换到嵌套的if语句用于我的递归方法,但我不确定这是否有助于或伤害了我的事业。
如果有人可以帮我解决这个问题,我会非常感激,因为我现在正式提出了想法。谢谢。
答案 0 :(得分:2)
看起来你陷入了无限的递归调用,不是因为你的基本情况有任何问题(虽然我不确定我理解内部比较是什么),但因为你实际上是在调用Heapify相同的元素。您的递归算法应该知道可能需要筛选的当前元素的索引。像这样:
private void insert(ArrayList<T> heap, T element) {
head.add(element);
heapify(heap, heap.size() - 1);
}
private void heapify(ArrayList<T> heap, int location) {
int parent = (location - 1) / 2; // -1 for zero-indexed language
// same-element comparison is OK. This will always happen at the root.
if (heap.get(parent).compareTo(heap.get(location)) > 0) {
swap(heap, location, parent);
heapify(heap, parent);
}
}
private void swap(ArrayList<T> heap, int a, int b) {
T temp = heap.get(a);
heap.set(a, heap.get(b));
heap.set(b, temp);
}
CLRS在第151-159页上对堆进行了非常出色的讨论。