Java堆排序实现+封装

Java堆排序实现+封装

对应AcWing838

import java.util.*;

class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        
        Heap heap = new Heap();
        for (int i = 0; i < n; i ++) {
            heap.insert(sc.nextInt());
        }
        heap.init();
        for (int i = 1; i <= m; i ++) {
            System.out.print(heap.getTop() + " ");
            heap.removeTop();
           
        }
    }   
    
    static class Heap {
        private int[] tree = new int[100010];
        private int size = 0;
        
        // 这里的insert操作,不去做向上的比较交换了,而是使用另一种方法
        public void insert(int x) {
            size ++;
            tree[size] = x;
        }
        
        // 用down操作去实现初始化。由于最后一个结点的父节点就是最后一个非叶子结点,所有可以从它开始比较。
        public void init() {
        	for (int i = size / 2; i >= 1; i --) {
            	down(i);
       		}
        }
        
        // 取堆顶
        public int getTop() {
            return tree[1];
        }
        // 删除堆顶,使用最后一个结点来替代,同时把size变小删除最后一个结点。
        public void removeTop() {
            tree[1] = tree[size];
            size --;
            down(1);
        }
        
        // 修改指定的结点
        public void modify(int i, int x) {
            tree[i] = x;
            down(i);
            up(i);
        }
        
        // 删除指定的结点
        public void remove(int i) {
            tree[i] = tree[size --];
            down(i);
            up(i);
        }
        
        // 最精彩的down
        private void down(int i) {
        	// 根据完全二叉树的性质得到的左右孩子结点
            int left = i * 2, right = i * 2 + 1;
            int t = i;
            // 比较左孩子是不是更小
            if (i * 2 <= size && compare(tree[left], tree[t]) < 0) t = left;
            // 比较右孩子是不是最小
            if (i * 2 + 1 <= size && compare(tree[right], tree[t]) < 0) t = right;
            // 如果孩子节点更小了,那么就进行交换,并且朝孩子节点往下遍历
            if (i != t) {
                swap(i, t);
                down(t);
            }
        }
        
        // up操作,正常情况下插入使用,但是此处不需要
        private void up(int i) {
            int parent = i / 2;
            while (parent != 0) {
                if (compare(tree[i], tree[parent]) < 0) {
                    swap(i, parent);
                }
                parent = parent / 2;
            }
        }
        
        // 交换结点
        private void swap(int i, int parent) {
            int t = tree[i];
            tree[i] = tree[parent];
            tree[parent] = t;
        }
        
        // compare函数,由于此处是小顶堆所以用 x-y,这里也可以自己取修改compare方式。
        public int compare(int x, int y) {
            return x - y;
        }
        
        
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值