堆:
堆是有如下特点的二叉树:
1、它是完全二叉树,即树的最后一层不要求是满的,第一个空结点开始的结点,左边所有的兄弟结点必须全部不为空,右边所有结点必须全部为空。
2、常常用一个数组来实现。
3、堆中每个结点的关键字都大于等于它的孩子结点的关键字。而左右孩子结点间没有强制规定大小关系。
所以根据3,我们可以知道,堆是一种弱有序的数据结构。
下面用Java实现堆的操作,包括向堆插入结点到堆尾,并进行向上调整,移除堆顶的元素,把堆尾元素移到堆顶并进行调整,更改堆元素的值并进行调整,输出堆中元素等方法。
package test2;
class HeapNode{
private int key;
public HeapNode(int key){
this.key = key;
}
public void setKey(int key){
this.key = key;
}
public int getKey(){
return key;
}
}
public class Heap {
private HeapNode[] heapArray;
private int maxSize;
private int currentSize;
public Heap(int maxSize){
this.maxSize = maxSize;
heapArray = new HeapNode[maxSize];
currentSize = 0;
}
public boolean insertNode(int key){
if(maxSize == currentSize){
return false;
}
HeapNode newNode = new HeapNode(key);
heapArray[currentSize] = newNode;
trickleUp(currentSize);//插入在尾端,向上调整,比起插入在根结点向下调整要方便,因为前者只需跟父结点比较,后者要跟两个子结点比较。
++currentSize;
return true;
}
public void trickleUp(int index){//插入到堆最末的结点进行向上调整
int parentIndex = (index-1)/2;
while(parentIndex >= 0){
if(heapArray[index].getKey() > heapArray[parentIndex].getKey()){
HeapNode temp = heapArray[index];
heapArray[index] = heapArray[parentIndex];
heapArray[parentIndex] = temp;
index = parentIndex;
parentIndex = (index-1)/2;//记得对当前值的下标和其父结点的下标更新
}else{
return;
}
}
return;
}
public void trickleDown(int index){
int leftChild ;
int rightChild ;
HeapNode temp;
while(index < currentSize && index >= 0){
leftChild = 2*index + 1;
rightChild = 2*index + 2;
if(leftChild >= currentSize){//如果左孩子不存在
return;
}else if(rightChild >= currentSize){//如果左孩子存在,右孩子不存在
if(heapArray[leftChild].getKey() > heapArray[index].getKey()){
temp = heapArray[index];
heapArray[index] = heapArray[leftChild];
heapArray[leftChild] = temp;
index = leftChild;
}
}
else{//如果左右孩子都存在
if(heapArray[leftChild].getKey() > heapArray[rightChild].getKey()){
temp = heapArray[index];
heapArray[index] = heapArray[leftChild];
heapArray[leftChild] = temp;
index = leftChild;
}else{
temp = heapArray[index];
heapArray[index] = heapArray[rightChild];
heapArray[rightChild] = temp;
index = rightChild;
}
}//end of if-else
}//while
}//end of method
public boolean deleteRootNode(){
if(currentSize == 0){
return false;
}
HeapNode root = heapArray[0];//需要时可将其返回
heapArray[0] = heapArray[--currentSize];
trickleDown(0);//删除根结点后,将最后一个结点放到堆顶,对其向下进行调整;
return true;
}
public boolean changeNodeKey(int index, int newKey){
if(index < currentSize && index >= 0){
if(heapArray[index].getKey() > newKey){//若新值比当前值小,说明要把新值结点下沉
heapArray[index].setKey(newKey);
trickleDown(index);
}else{//若新值比当前值大,说明要把新值结点上升
heapArray[index].setKey(newKey);
trickleUp(index);
}
return true;
}
return false;
}
public void displayHeap(){
for(int i=0; i
System.out.print(" "+heapArray[i].getKey());
}
System.out.println(" ");
}
}
class HeapApp{
public static void main(String args[]){
Heap heap = new Heap(20);
heap.insertNode(1);
heap.insertNode(2);
heap.insertNode(3);
heap.insertNode(9);
heap.deleteRootNode();
heap.displayHeap();
heap.changeNodeKey(2, 8);
heap.displayHeap();
}
}测试结果:
3 1 2
8 1 3