堆排序Java实现

package aaa;

import java.util.*;
/* 堆排序,可以有效的降低时间复杂度
 * 建立一个大顶堆并且进行堆排序输出从小到大排序的数
 * 时间复杂度为O(NlogN)
 * 扩展:如果要求一个数列里面的第k大的数,只需要建立一个大小为k的小顶堆,并且不断调整维护(先选三个数建堆,后面的数逐个插入堆顶并进行删除调整),
 * 最后输出对堆顶元素即可
 * 同理,求解一个数列里面的第k小的数,只需要建立一个大小为k的大顶堆,
 * */
public class Main {
    static Scanner in = new Scanner(System.in);
    static int n;
    static int[] h = new int[1000];
    //交换数据值
    static void swap(int x ,int y){
    	int t;
    	t = h[x];
    	h[x] = h[y];
    	h[y] = t;
    }
    //注意:对于一个完全二叉树而言,第一个非叶子节点编号为n/2, 
    //构建大顶堆,从第一个非叶子节点开始逐个向下调整
    static void create(){
    	for (int i = n/2; i >= 1; i--) {
			shiftDown(i);
		}   	
    }
    //向下调整,i为当前叶子编号
    static void shiftDown(int i){
    	boolean f = true;//用来判断是否需要继续调整
    	int t ;
    	//如果有左子
    	while(i*2 <= n && f){
    		//和左子的值进行比较调整,更新t值
    		if(h[i]<h[i*2])   
    			t = i*2;
    		else
    			t = i;
    		//如果有右子,和右子的值进行比较调整更新t值
    		if(i*2+1 <= n){
    	   		if(h[t]<h[i*2+1])      		
        			t = i*2+1;       		
    		}
    		
    		//注意我们寻找的是左右子里面最大的值
    		//如果当前节点需要调整,交换调整
    	   if(t!=i){
    		   swap(t, i);
    		    i = t;//更新i的值,以便于进行下一次调整(下一层)
    	   }
    	   else
    		   f = false;//如果当前节点不需要调整,退出
    	}
    	
    }
    //由于要按照从小到大输出,所以把节点1和节点n交换,n--的意思是最终序列里面的最后的一个数已经确定
    //并且重新调整当前堆使之成为大顶堆,以此类推,每次找出当前数里面最大的数
    static void heapSort(){
    	while(n>1){
    		swap(1, n);
    		 n--;
    		shiftDown(1);
    		}   	
    }
	public static void main(String[] args) {

		n = in.nextInt();
	    int k = n;//保护n的值,用于输出
		for (int i = 1; i <= n; i++) {
			h[i] = in.nextInt();
		  }
        create();
        heapSort();
       for (int i = 1; i <= k; i++){ 
		 System.out.print(h[i]+" ");
	    }
       System.out.println();
	}

}

两个小错误:一、没有保护n的值; 二、t写成了i,求的是左右子里面最大的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值