Heap中文翻译过来叫做堆,但他并不是大家所说的内存中的堆栈区,而是一种用数组来实现的弱序的完全二叉树。他是一种数据结构。Heap 很像前面所说的二叉搜索树,但是他并没有二叉搜索树那样有严格的顺序规定。二叉搜索树中,父接点必须大于它的左孩子,而小于他的右孩子;但是在Heap中,只要规定父接点大于两个子接点就可以了,而且其中的每个元素并不是通过Link来连接的,而是对这个完全二叉树进行编号,然后放到数组中。由父接点的编号能找到相应的子接点的编号,反之亦然。
• Its parent is (x–1) / 2
• Its left child is 2*x + 1
• Its right child is 2*x + 2
Heap的作用可以看成是一个优先级队列,他并不能实现查找某个接点的功能,因为Heap是一个弱序的二叉树,他是搜索不到要找的接点的。但是Heap可以像一个优先级队列一样,支持删除最大(最小)的接点(因为删除都是删除根,而根通常是整个树中最大的或者最小的接点),插入新接点。
插入接点就是将新接点插入到数组的最后一个位置,也就是二叉树的第1个空位上。然后将这个接点向上遍历,直到找到他合适的位置,也就是第1个大于他的父接点。
public boolean insert(int key)
{
if(arraySize == maxSize)
return false;
Node newNode = new Node(key);
heapArray[arraySize++] = newNode;
trickleUp(arraySize);//将这个接点向上遍历,以找到合适的位置
return true;
}
删除接点就是将root删除,然后将二叉树中的最后一个元素移至root,再向下便利以找到合适的位置。向下遍历比向上遍历要麻烦的一点就是要比较出子接点中较大的,然后再比较此接点,如果小于大点的子接点就和大的子接点互换位置。
public Node remove()
{
Node temp = heaparray[0];
heapArray[0] = heapArray[--arraySize];
tricleDown(0);
return temp;
}
除了实现了insert 和remove之后,再多实现一个change(),这个方法用于改变特定Node的key,就像在优先级 队列中改变一个元素的优先级别一样。
public boolean change(int key,Node newNode)
{
if(key<0||key>arraySize)
return false;
Node oldNode = heapArray[key];
heapArray[key] = newNode;
if(oldNode.iData<newNode.iData)
trickleDown(key);
else
trickleUp(key);
return true;
}
写到这儿,其实实现Heap最难的无非是trickleDown和trickleUp方法了。
public void trickeUp(int index)
{
Node temp = heapArray[index];
parent = index/2;
while(index>0&&heapArray[index]>heapArray[parent])
{
heapArray[index] = heapArray[parent];
index = index/2;
parent = index/2;
}
heapArray[index] = temp;
}
public void trickleDown(int index)
{
Node temp = heapArray[index];
int larger;
while(index<arraySize/2)
{
if(index*2+2<arraySize&&heapArray[index*2+1]<heapArray[inde*2+2])
larger = index*2+2;
else
larger = index*2+1;
if(heapArray[index]>heapArray[larger])
break;
heapArray[index] = heapArray[larger];
index = larger;
}
heapArray[index] = temp;
}