堆排序

大顶堆构造+堆顶值取出(注:下标从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;
		}
}

点赞