大顶堆构造+堆顶值取出(注:下标从0开始)
大小顶堆需满足条件:左右孩子需大于/小于父节点,左右孩子之间无具体关联;
package work.算法优先级队列;
import java.util.Arrays;
public class main {
public static void main(String[] args){
int[] arr={1,2,3,4,5,6,7};
sort(arr); //对数组进行排序;
System.out.println(Arrays.toString(arr)); //输出 ;
}
public static void sort(int[] arr) {
int length=arr.length; //arr.length/2-1为最后一个非叶子节点;
for(int i=arr.length/2-1;i>=0;i--) { //for循环目的:从最后一个非叶子节点开始从下至上,从右至左开始调节;
adjust(arr,i,arr.length); //for循环完成后,初始的大顶堆构造完毕;
}
for(int i=arr.length-1;i>0;i--) { //目的:将数组按从小到大顺序排列;
//下标从0开始,所以i最大为arr.length-1;
length=length-1; //每次将最大的元素与堆尾元素交换位置,然后调节arr.length--的
swap(arr,0,i); //元素继续满足堆的性质;
adjust(arr,0,length);
}
} //i结点为父节点,假设左右孩子本身满足大顶堆的性质;;;
public static void adjust(int[] arr,int i,int length) { //目的:调节使得堆满足其必要性质;
int l=2*i+1; //表示出下表为i时的左右孩子下标大小;
int r=2*i+2;
int max; //然后用max表示三个节点中数值最大的那一个的下标;
if(l<length&&arr[l]>arr[i]) {
max=l;
}
else {
max=i;
}
if(r<length&&arr[r]>arr[max]) {
max=r;
}
if(max!=i) { //判断,最大的数值下标是不是原先的i,若是,直接满足大顶堆的性质,不必向下进行操作;
swap(arr,i,max); //若不是,则将父节点交换成最大的那个值,原来i所对应的值,在交换后可能会使得以他为父节点的子树,不满足大顶堆的性质,故,将他惊醒递归调用,一直到满足为止;
adjust(arr,max,length);
}
}
public static void swap(int[] arr,int a,int b) {
int temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
}