优先队列堆:修复 bubbleDown 方法

Priority Queue Heap: fixing bubbleDown method

我正在研究优先级队列(堆),我认为我有很好的基础。我认为我的方法大部分都有意义,但在我的 bubbleDowndeleteMin 方法上确实很吃力。

public class Heap {
    private int n;
    private Node[] s;

    public Heap() {
        s =  new Node[128];
        n =0;
    }

    public boolean isEmptySet() {
        return (n == 0);
    }   

    public Node findMin() {
        return s[0];
    }

    public void insert(Node p) {
        s[n] = p;
        n = n+1;
        bubbleUp(n - 1); // needs to subtract 1 because we do the addition
        }

    public void bubbleUp(int index) {
        if (index == 0) {
            return index;
        }

        else if (index > 0) {
            int parentIndex = (index - 1) / 2; // Might not need to subtract 1
            if (s[index].getKey() < s[parentIndex].getKey()) {
                swapNode(index, parentIndex);
                bubbleUp(parentIndex);
            }
        }
    }

    public void swapNode(int index, int parentIndex) {
        Node temp = s[index];
        s[index] = s[parentIndex];
        s[parentIndex] = temp;
    }

    public void deleteMin(Node p) {
        n = n - 1;
        bubbleDown(s[0], s[n]);
        return s[n];
    }


    public void bubbleDown(int index) {
        if (index < 0) {
            int leftChildIndex = (i*2) + 1;
            int rightChildIndex = (i*2) + 2;
            if (s[index].getKey() > s[leftChildIndex].getKey()) {
                swapNode(index, leftChildIndex);
                bubbleDown(leftChildIndex);
            } else if (s[index].getKey() < s[leftChildIndex].getKey() && s[index].getKey() > s[rightChildIndex].getKey()) {
                swapNode(index, rightChildIndex);
                bubbleDown(rightChildIndex);
            }
        }
    }
}

首先,在您的 bubbleUp() 中,您确实需要减去 1 才能找到 parent。考虑到 0 的 children 是 1 和 2。如果您在除法之前没有减去 1,那么 2 的 parent 将被错误地计算为 1。

在您的 findMin() 中,您应该在盲目返回根项之前检查是否有空堆。我知道你有一个 isEmptySet() 函数,但是如果你为空堆调用它 findMin() 应该抛出异常。

现在,在你的 deleteMin()bubbleDown() 上。 deleteMin 应该是:

public void deleteMin(Node p){
    n = n - 1;
    // place root node at the end of the heap,
    // and the last node at the root.
    swapNode(0, n);

    // adjust the heap
    bubbleDown(0);
    return s[n];
}

按照您的方式,deleteMin 将节点而不是节点索引传递给 bubbleDown,并且当 bubbleDown 只接受一个参数时它传递了两个参数。

您的 bubbleDown 方向是正确的,但您必须小心。向下冒泡的规则是,如果该节点大于其 children 中的任何一个,则将节点与两个 children 中最小的节点交换。而且你不能盲目检查两个潜在的 children,因为节点可能根本没有 children。所以:

public void bubbleDown(int index){
    int childIndex = (index * 2) + 1;
    if (childIndex > n)
    {
        // if the first child index is off the end of the heap
        // then the item has no children. (It's a leaf.)
        return;
    }

    // first find the smallest child
    // This test is to prevent checking a right child that doesn't exist.
    if (childIndex < n)
    {
        if (s[childIndex] > s[childIndex+1])
        {
            childIndex = childIndex + 1;
        }
    }

    // childIndex holds the index of the smallest of the node's children.
    // swap if the parent is larger than the smallest child,
    // and then keep bubbling down.
    if (s[index] > s[childIndex])
    {
        swapNode(index, childIndex);
        bubbleDown(childIndex);
    }
}