从最小堆中添加或删除元素

时间:2018-11-24 20:49:27

标签: java heap

我正在尝试创建一个最小堆,但是我遇到了一个问题,即我的最小堆中显示的数字都是随机排列的,并且存在多余的0,其中应该有不同的值。这是我班上完成大部分工作的代码:

public class Heap211 {
static Random rand = new Random();
static public int[] Heap;
static public int size;

Heap211(){
    Heap = new int[30];
    size = 0;
}
static public int parent(int index){//location of parent
    return index / 2;//array[k / 2]
}
static public int leftChild(int index){//location of left child
    return index * 2;//array[k * 2]
}
static public int rightChild(int index){//location of right child
    return index * 2 + 1;//array[k * 2 + 1]
}
static public boolean hasParent(int index){
    return index > 1;
}
static public boolean hasLeftChild(int index){
    return leftChild(index) * 2 <= size;
}
static public boolean hasRightChild(int index){
    return rightChild(index * 2) + 1 <= size;
}
static public void swap(int[] a, int index1, int index2){//swaps nodes
    int temp = a[index1];
    a[index1] = a[index2];
    a[index2] = temp;
}
static public int peek(){//peeks at the top of the stack (min value)
    return Heap[1];
}
public static boolean isEmpty(){
   return size == 0;
}
static int randInt(int min, int max){//generates random int between two numbers 
    return ((int) (Math.random()*(max - min))) + min; 
}
public String toString(){
    String result = "[";
    if(!isEmpty()){
        result += Heap[1];
        for(int i = 2; i <= size; i++){
            result += ", " + Heap[i];
        }
    }
    return result + "]";
}
public void add(int value){//adds the give value to this priority queue in order
    if(size + 1 >= Heap.length){
        Heap = Arrays.copyOf(Heap, Heap.length * 2);
    }
    size++;
    Heap[size + 1] = value;//add as rightmost leaf

    //"bubble up" as necessary to fix ordering
    int index = size + 1;
    boolean found = false;
    while(!found && hasParent(index) && hasLeftChild(index)){
        int parent = parent(index);
        if(Heap[index] < Heap[parent]){
            swap(Heap, index, parent(index));
            index = parent(index);
        }else{//after done bubbling up
            found = true;
        }
    }
}
public int remove(){
    //move rightmost leaf to become new root
    int result = peek();//last leaf -> root
    Heap[1] = Heap[size];
    size--;

    //"bubble down" as necessary to fix ordering
    int index = 1;
    boolean found = false;
    while(!found && hasLeftChild(index)){
        int left = leftChild(index);
        int right = rightChild(index);  
        int child = left;
        if(hasRightChild(index) && Heap[right] < Heap[left]){
            child = right;
        }
        if(Heap[index] > Heap[child]){
            swap(Heap, index, child);
            index = child;
        }else{
            found = true;//found proper location, stop the loop
        }
    }
    return result;
}

这是我的主要课程的代码:

    public static void main(String[] args){
    Heap211 pq = new Heap211();
    for(int node = 1;node <= 30; node++){//loop runs 30 times for 30 nodes
        int smValue = randInt(0,2);//generates random number between 1 and 0
        if(smValue == 0){//if random number is 0 then it will add random number to heap
            int value = randInt(0,100);//generates random number between 0 and 100
            System.out.println(node + " Add " + value + ": ");
            pq.add(value);//adds random number
            System.out.println(pq);//print heap

        }else if(smValue == 1 && pq.isEmpty()){
            int value = pq.remove();
            System.out.println(node + " Remove " + value + ": ");
            System.out.println(pq);
        }
    }

我有一个显示所有数字的GUI,但输出错误。任何有用的指针将不胜感激!谢谢。

1 个答案:

答案 0 :(得分:0)

我在您的代码中发现了一些问题。

您的hasLeftChild函数错误。您有return leftChild(index*2) <= size;。但是您确实应该检查leftChild(index) <= size。您的hasRightChild函数中存在类似的错误。

不确定为什么将数组参数传递给swap。交换内容的唯一数组是Heap数组,它是该类的成员。

您的add方法出错。您增加大小,然后添加一个项目。那就是:

size++;
Heap[size + 1] = value;

因此,想象一下添加第一项时会发生什么。 size等于0,然后将其递增到1。然后将值添加到索引size+1。因此,您的数组包含[0, 0, value]。那可能是您额外的0的来源。我想您想要的是:

Heap[size] = value;
size++;

您必须修改其余代码以将其考虑在内。

您的“冒泡”循环有点古怪。你有:

while (!found && hasParent(index) && hasLeftChild(index))

这永远不会使任何事情冒泡,因为当您向堆的最后一个元素中添加内容时,该节点没有左子节点。您也不需要found标志。您可以编写:

while (hasParent(index) && Heap[index] < Heap[parent]]) {
    swap(Heap, index, parent(index));
    index = parent(index);
}

我不能保证这些是您代码中唯一的错误,但是它们是我在快速查看您的代码时发现的那些错误。

总的来说,为什么世界上都使用一种基于0的数组的语言创建基于1的二进制堆?不需要这样做,这很混乱。关于为什么我认为这是个坏主意,请参阅https://stackoverflow.com/a/49806133/56778http://blog.mischel.com/2016/09/19/but-thats-the-way-weve-always-done-it/

最后,您应该按照注释中的建议学习使用调试器。花些时间现在现在。这样可以节省您数小时的沮丧时间。