[英]Java Arraylist Heap Implementation
我正在尝试为基于arraylist的堆实现实现insert()
方法,但是每当我测试该方法插入多个整数(其中至少一个整数大于4)时,该程序将永远运行。 例如,在main函数中同时声明heap.insert(1)
和heap.insert(8)
将永远花费时间。 这是我的堆类:
import java.util.*;
public class Heap<E extends Comparable<E>> implements HeapAPI<E>
{
/**
* A complete tree stored in an array list representing this
* binary heap
*/
private ArrayList<E> tree;
/**
* Constructs an empty heap
*/
public Heap()
{
tree = new ArrayList<E>();
}
public boolean isEmpty()
{
return tree.isEmpty();
}
public void insert(E obj)
{
tree.add(tree.size(), obj);
siftUp(tree.size() - 1);
}
/**
* siftUp from position k. The key or node value at position
* may be greater that that of its parent at k/2.
* @param k position in the heap arraylist
*/
private void siftUp(int k)
{
E v = tree.get(k);
while (v.compareTo(tree.get(k / 2)) == 1)
{
tree.add(k, tree.get(k / 2));
k = k / 2;
}
tree.add(k, v);
}
public int size()
{
return tree.size();
}
}
这是我的教授给我们的伪代码,我从以下位置对insert()
和siftUp()
方法进行了建模:
该程序适用于较小的整数,例如,如果我连续多次键入heap.insert(1)
,但如果将其中一个数字更改为较大的整数,则永远无法完成运行。 没有抛出任何错误,因为当我尝试运行该程序时,它没有完成执行。 我不确定发生了什么。 任何帮助表示赞赏。
让我们在这里浏览一下代码:
public void insert(E obj)
{
tree.add(tree.size(), obj);
siftUp(tree.size() - 1);
}
private void siftUp(int k)
{
E v = tree.get(k);
while (v.compareTo(tree.get(k / 2)) == 1)
{
tree.add(k, tree.get(k / 2));
k = k / 2;
}
tree.add(k, v);
}
现在,您执行tree.insert(1)
,一切正常。 接下来,您调用tree.insert(0)
。 让我们看看发生了什么。
tree.add(tree.size(), obj)
将0添加为数组列表中的下一项。 因此,您现在有了一个包含[1, 0]
的列表 siftUp(1)
siftUp
,第一行从数组列表中获取元素1。 此时, v = 1
while
语句中,代码将值1与tree[k/2]
处的值进行比较。 因为k == 1
,所以您要检查根节点(即tree[0]
),我们知道它等于1。 [1, 1]
。 k
除以2,得到0。 while
条件。 k
等于0,并且tree[k]
值为1,这意味着它仍大于v的值。 问题是您的循环没有确定的结束条件。
解决问题的一种方法是在k == 0
结束循环。
private void siftUp(int k)
{
E v = tree.get(k);
while (k > 0 && v.compareTo(tree.get(k / 2)) == 1)
{
tree.add(k, tree.get(k / 2));
k = k / 2;
}
tree.add(k, v);
}
下一个麻烦是父节点的计算不正确。 如果堆的根节点在索引0处,那么对于索引ix
处的节点,其左子节点在(ix*2)+1
,而右子节点在(ix*2)+2
。 节点的父节点位于(ix-1)/2
。
考虑具有三个节点的堆:
0
1 2
这里的节点号与数组索引相同。
如果根在索引0处,则左侧节点在(2 * 0)+ 1处。右侧节点在(2 * 0)+ 2处。1的父节点是(1-1)/ 2。 2的父级是(2-1)/ 2。 在您的代码中,父计算为k/2
,对于上面堆中标记为2的节点,其错误值为1。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.