1.什么是堆
堆是一种特殊的数据结构,通常是一个可以被看做一棵树的数组对象。它使用数组保存二叉树结构,即将二叉树用层序遍历结果放入数组中。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆
2.堆满足的性质
- 堆中某个节点的值总是不大于或不小于其父节点的值;
- 堆总是一棵完全二叉树。
2.1 已知双亲结点(parent)下标
左节点(leftIndex)=parent2+1 ;
右节点(rightIndex)=parent2+2;
2.2 已知子结点(不区分左右)(child)下标
父节点(parentIndex)=(child-1)/2;
3.堆的一些操作
3.1 向下调整
前提:左右子树已经满足堆的性质
实现:
//小堆
public static void smallHeapAdjustDown(long[]array,int size,int index){
while(index*2+1<size){//叶子结点存在
int minIndex=index*2+1;//现将最小值的下标定为左节点的下标
int rightIndex=minIndex+1;
if(rightIndex<size&&array[rightIndex]<array[minIndex]){
//右结点存在并且右结点的值小于左节点的值时将最小值的下标变为右结点
minIndex=rightIndex;
}
//当父节点的值已经小于等于最小的子节点的值时结束向下调整
if(array[index]<=array[minIndex]){
break;
}
swap(array,index,minIndex);//交换父节点和最小子节点的值
index=minIndex;//将index变为minIndex继续循环
}
}
private static void swap(int[] array, int index, int minIndex) {
int t=array[index];
array[index]=array[minIndex];
array[minIndex]=t;
}
测试:
3.2 建堆
给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但是还不是一个堆,现在我们通过算法,把它构建成一个堆。根节点左右子树不是堆,我们怎么调整呢?这里我们从倒数的第一个非叶子节点的子树开始调整,一直
调整到根节点的树,就可以调整成堆。
- 实现
public static void createHeap(int []array){
int index=array.length-1;
index=(index-1)/2;
for(int i=index;i>=0;i--){
bigHeapAdjustDown(array,array.length,i);
}
}
private static void bigHeapAdjustDown(int[]array,int size,int index){
while(index*2+1<size){
int maxIndex=index*2+1;
if(maxIndex+1<size&&array[maxIndex+1]>array[maxIndex]){
maxIndex++;
}
if(array[index]>=array[maxIndex]){
break;
}
swap(array,index,maxIndex);
index=maxIndex;
}
}
private static void swap(int[] array, int index, int minIndex) {
int t=array[index];
array[index]=array[minIndex];
array[minIndex]=t;
}
测试:
3.3优先级队列的实现
public class MyPriorityQueue {
private int []array;
private int size;
MyPriorityQueue(){
this.array=new int[100];
size=0;
}
public boolean add(int val){
if(size>=array.length){
return false;
}
array[size++]=val;
adjustUp(size-1);
return true;
}
private void swap(int[] array, int index, int minIndex) {
int t=array[index];
array[index]=array[minIndex];
array[minIndex]=t;
}
private void adjustUp(int index) {
while(index>0){
int parentIndex=(index-1)/2;
if(array[parentIndex]>array[index]){
break;
}
swap(array,parentIndex,index);
index=parentIndex;
}
}
public int poll() {
if (size == 0) {
return -1;
}
int val = this.array[0];
array[0] = array[size-1];
size--;
bigHeapAdjustDown(0);
return val;
}
public void bigHeapAdjustDown(int index){
while(index*2+1<size){
int maxIndex=index*2+1;
if(maxIndex+1<size&&array[maxIndex+1]>array[maxIndex]){
maxIndex++;
}
if(array[index]>=array[maxIndex]){
break;
}
swap(array,index,maxIndex);
index=maxIndex;
}
}
}