在整个堆中恢复堆条件

时间:2013-03-29 18:35:20

标签: java heap heapsort

我正在尝试回答以下编程问题:

在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()

有什么想法吗?帮助赞赏。

1 个答案:

答案 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);
    }
}