我正在尝试回答以下编程问题:
在heap.java程序中,insert()
方法在堆中插入一个新节点,并确保保留堆条件。编写一个toss()
方法,将新节点放入堆数组中,而不尝试维护堆条件。 (也许每个新项都可以简单地放在数组的末尾。)然后编写一个restoreHeap()
方法,在整个堆中恢复堆状态。在必须同时插入大量数据时,重复使用toss()
后跟单个restoreHeap()
比重复使用insert()
更有效。有关线索,请参阅heapsort的说明。要测试你的程序,插入一些项目,再扔一些,然后恢复堆。
我已经为折腾函数编写了代码,该函数在最后成功插入了节点,并没有修改堆条件。我遇到了restoreHeap
函数的问题,但我无法绕过它。我已经包含了以下两个功能。
heap.java的完整代码是here(包括toss()
和restoreHeap()
)
toss()
- 我基于插入函数
public boolean toss(int key)
{
if(currentSize==maxSize)
return false;
Node newNode = new Node(key);
heapArray[currentSize] = newNode;
currentSize++;
return true;
} // end toss()
restoreHeap()
- 我基于trickleUp函数,我得到了一个StackOverflowError。
public void restoreHeap(int index)
{
int parent = (index-1) / 2;
Node bottom = heapArray[index];
while( index > 0 &&
heapArray[parent].getKey() < bottom.getKey() )
{
heapArray[index] = heapArray[parent]; // move it down
index = parent;
parent = (parent-1) / 2;
} // end while
heapArray[index] = bottom;
while(index != 0)
{
restoreHeap(parent++);
}
} // end restoreHeap()
有什么想法吗?帮助赞赏。
答案 0 :(得分:1)
我会试一试。这是一种通过一些解释来做你所要求的方法。
由于您知道堆中所有节点的一半是叶子,而叶子本身就是一个有效的堆,因此您只需要遍历另一半节点以确保它们也是有效的。如果我们从底层向上执行此操作,我们可以在堆栈中保持有效的堆结构“低于”。这可以通过for
循环轻松完成:
public void rebuildHeap()
{
int half = heapArray.length / 2;
for(int i = half; i >= 0; i--)
restoreHeap(i);
}
如何实施restoreHeap
?
它应该检查index
节点对其子节点是否需要重新定位节点。因为我们确保index
节点下面的树是堆,我们只需要将index
节点移动到正确的位置。因此我们将它在树中移动。
首先我们需要找到孩子。由于三个节点中的每一行节点都是之前行的两倍,因此子节点的位置如下:
private void restoreHeap(int index)
{
int leftChild = (index * 2) + 1; //+1 because arrays start at 0
int rightChild = leftChild +1;
...
现在您只需要将儿童价值与您的index
节点值进行比较。如果子级具有更大的值,则需要将index
节点与子节点交换。如果两个子节点都有更大的值,则需要与具有最大值的子节点交换(在交换后保持堆结构)。交换节点后,您需要再次调用该方法,以查看是否需要将index
节点向下移动到树下。
...
int biggest = index;
if(leftChild < currentSize && heapArray[leftChild].getKey() > heapArray[index].getKey())
biggest = leftChild; //LeftChild is bigger
if(rightChild < currentSize && heapArray[rightChild].getKey() > heapArray[biggest].getKey())
biggest = rightChild; //RightChild is bigger than both leftChild and the index node
if(biggest != index) //If a swap is needed
{
//Swap
Node swapper = heapArray[biggest];
heapArray[biggest] = heapArray[index];
heapArray[index] = swapper;
restoreHeap(biggest);
}
}