1.堆的构建(大根堆):
package com.hfm.util;
import java.util.Arrays;
public class Heap {
int arr[];
public Heap(int[] arr) {
this.arr = arr;
print(arr);
build(arr,arr.length-1,arr.length-1);
print(arr);
}
private int getHeight(int arr[]){
return (int)Math.ceil(Math.log(1+arr.length)/Math.log(2));
}
private static void print(int arr[]){
int height = 0,count = 0;
System.out.println();
while(count<arr.length){
int num = ((int) Math.pow(2, height));
for(int i=0;i<num&&(count<arr.length);i++){
System.out.print(arr[count]+" ");
count ++;
}
height++;
System.out.println();
}
System.out.println();
}
private void swap(int arr[],int x,int y){
arr[x] += arr[y];
arr[y] = arr[x] - arr[y];
arr[x] = arr[x] - arr[y];
}
private void sort(){
for (int i = arr.length-1; i >0; i--) {
swap(arr,0,i);
adjust(arr,i-1,i-1);
}
print(arr);
}
private void adjust(int arr[],int end,int visited){ // 大根堆的调整
if(visited==0)
return;
int parent = ((int) Math.ceil(end / 2.0))-1>-1? ((int) Math.ceil(end / 2.0))-1:0,last = 0;
while (parent>-1){
if(arr[end]>arr[parent]){
swap(arr,end,parent);
last = parent;
end = parent;
parent = ((int) Math.ceil(parent / 2.0))-1>-1? ((int) Math.ceil(parent / 2.0))-1:0;
continue;
}
break;
}
//交换叶子节点最大值和当前值
int res[] = null;
while((res = maxLeaf(arr,last))[0]!=-Integer.MAX_VALUE){
if(res[0] != -Integer.MAX_VALUE){
if(arr[last]<arr[res[1]]&&res[1]<end){
swap(arr,res[1],last);
}
last = res[1];
}
}
adjust(arr,--visited,visited);
}
/**
* 大根堆的构建,根据传入的数组进行构建,使用递归的思想
* 从叶子节点开始,从第一个非叶子节点开始往前依次调整,直到根节点
* @param arr
* @param curNotLeaf 当前节点下标
* @param visited 当前被访问或被处理过的节点下标
*/
private void build(int arr[],int curNotLeaf,int visited){ // 大根堆的构建
if(visited==0)
return;
int parent = ((int) Math.ceil(curNotLeaf / 2.0))-1>-1? ((int) Math.ceil(curNotLeaf / 2.0))-1:0,//当前节点的父节点下标
last = 0; //记录下交换的最后位置的下标,方便后续从该节点开始向下回溯
while (parent>-1){//向上寻找,直到父节点下表对应的值已经满足大根堆的条件为止
if(arr[curNotLeaf]>arr[parent]){
swap(arr,curNotLeaf,parent);
last = parent;
curNotLeaf = parent;
parent = ((int) Math.ceil(parent / 2.0))-1>-1? ((int) Math.ceil(parent / 2.0))-1:0;
continue;
}
break;
}
//交换叶子节点最大值和当前值
int res[] = null;
while((res = maxLeaf(arr,last))[0]!=-Integer.MAX_VALUE){
if(res[0] != -Integer.MAX_VALUE){
if(arr[last]<arr[res[1]]){
swap(arr,res[1],last);
}
last = res[1];
}
}
build(arr,--visited, visited);
}
/**
* 去除当前节点的子节点中最大值和它对应的下标
* 若无子节点,则返回最小整数
* @param arr
* @param index
* @return
*/
private int[] maxLeaf(int arr[],int index){
if(index*2+1>arr.length-1)
return new int[]{-Integer.MAX_VALUE,-Integer.MAX_VALUE};
if(index*2+2>arr.length-1)
return new int[]{arr[index*2+1],index*2+1};
else
return arr[index*2+1]>=arr[index*2+2]?new int[]{arr[index*2+1],index*2+1}:new int[]{arr[index*2+2],index*2+2};
}
public static void main(String[] args) {
Heap heap = new Heap(new int[]{5,8,13,2,7,12,15,2});
heap.sort();
}
}
2.堆的典型应用:堆排序,top-k问题等