堆排序

输入一个长度为 n 的整数数列,从小到大输出前 m 小的数。

输入格式
第一行包含整数 n 和 m。

第二行包含 n 个整数,表示整数数列。

输出格式
共一行,包含 m 个整数,表示整数数列中前 m 小的数。

数据范围
1≤m≤n≤105,
1≤数列中元素≤109
输入样例:
5 3
4 5 1 3 2
输出样例:
1 2 3

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Created with IntelliJ IDEA.
 *
 * @Auther: zlf
 * @Date: 2021/04/17/20:55
 * @Description: 堆排序 每次输出最小的 这是小顶堆
 */
public class Main {

	/**
        对于二叉树堆来说,用层次遍历(左到右)的存储来讲 如果一个节点在数组中的下标是 n 那左节点就是 2*n 右节点 2*n+1
    */

    static int size = 0;

    public static void swap(int h[],int i,int j){
        int t = h[i];
        h[i] = h[j];
        h[j] = t;
    }
    
    
    public static void down(int u,int h[]){
        int t = u;
        // 与左右儿子进行比较
        if(u*2 <= size && h[u*2] < h[t]) t = u*2;
        if(u*2+1<= size && h[u*2+1] < h[t]) t = u*2+1;
        // 交换
        if(t!=u){
            swap(h,u,t);
            // 接着向下比较 
            down(t,h);
        }
    }

	public static void up(int u,int h[]){
        // u/2 > 0 判断父节点是否存在   如果存在,父节点大于子节点就交换
        while(u/2>0 && h[u/2] > h[u]){
            swap(h,u,u/2);
            u/=2;
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader read = new BufferedReader(new InputStreamReader(System.in));

        String []s = read.readLine().split(" ");
        int n = Integer.valueOf(s[0]).intValue();
        int m = Integer.valueOf(s[1]).intValue();
        String[] str = read.readLine().split(" ");
        int h[] = new int[str.length+1];
        for (int i = 1; i <= n; i++) {
            h[i] = Integer.valueOf(str[i-1]).intValue();
        }
        size = n;
        for (int i=n/2;i>=0;i--) down(i,h);
        while (m-->0){
            down(1,h);
            System.out.print(h[1]+" ");
            // 将最小值删除 只需要用末尾元素替换即可
            h[1] = h[size];
            size--;
            // 重新向下比较
            down(1,h);
        }

    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值