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;
}
}
}