1.堆是由一棵完全二叉树构成,如下图所示:
大根堆就是头结点是堆的最大值,每一个子树头结点的值也算是其最大值。
小根堆是头结点是堆的最小值,每一个子树头结点的值也算是其最小值。
构造一个大根堆或者的方法就是子与父比较,若比父大则上浮取代父的位置,若比父小,则停在这个位置。小根堆类似。
大根堆的插入代码如下:
public static void swap(int arr[],int i,int j){
int tem=arr[i];
arr[i]=arr[j];
arr[j]=tem;
}
//大根堆的构造(上浮操作)
public static void heapInsert(int[] arr,int index){
while(arr[index]>arr[(index-1)/2]){
swap(arr,index,(index-1)/2);
index=(index-1)/2;
}
}
取出一个大根堆中最大的数字:
将数字取出,然后将最后一个数移到第一个位置,然后那个位置的数进行下沉操作。与子节点比较大小,若比子节点小,则与其交换位置。
下沉的代码如下:
//下沉操作
public static void heapify(int[] arr,int index,int heapSize){
int left=index*2+1; //左孩子的下标
while(left<heapSize){// 下方是否还有孩子
int largest = left+1<heapSize && arr[left+1]>arr[left]
?left+1:left; //判断哪个孩子大,把大的下标给largest
//比较父亲和大孩子哪个更大
largest = arr[largest]>arr[index]?largest:index;
if(largest==index){
break; //父亲比孩子大
}
swap(arr,largest,index);
left=index*2+1;
}
}
2.堆排序:
将堆顶的值与堆末尾的值交换,堆的大小减一,然后此时堆顶元素下渗。直到最后堆的容量减到0为止。
public static void heapSort(int[] arr){
if(arr==null || arr.length<2){
return;
}
for (int i = 0; i < arr.length; i++) {
heapInsert(arr,i);
}
int heapSize = arr.length;
swap(arr,0,--heapSize);
while(heapSize>0){
heapify(arr,0,heapSize);
swap(arr,0,--heapSize);
}
}
时间复杂度O(logN)。