优先级队列堆:修复bubbleDown方法

时间:2016-11-10 01:24:03

标签: java heap priority-queue

我正在研究优先级队列(堆)并认为我有一个良好的基础。我认为我的方法在大多数情况下都有意义但在我的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);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

首先,在bubbleUp()中,您需要减去1才能找到父级。考虑0的子项为1和2.如果在除法之前没有减去1,那么2的父项将被错误地计算为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走在正确的轨道上,但您必须小心。冒泡的规则是,如果节点大于其子节点,则将节点与两个子节点中的最小节点交换。并且你不能盲目地检查两个潜在的孩子,因为节点可能根本没有孩子。所以:

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