我正在尝试创建一个最小堆,但是我遇到了一个问题,即我的最小堆中显示的数字都是随机排列的,并且存在多余的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,但输出错误。任何有用的指针将不胜感激!谢谢。
答案 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/56778和http://blog.mischel.com/2016/09/19/but-thats-the-way-weve-always-done-it/。
最后,您应该按照注释中的建议学习使用调试器。花些时间现在现在。这样可以节省您数小时的沮丧时间。