个人认为讲的比较好的一篇博客
https://www.jianshu.com/p/6b526aa481b1
import java.util.Scanner;
/**
* 手写堆
* 1. 插入一个数
* heap[++size]=x
* up(size)
* 2. 求集合当中的最小值
* heap[1]
* 3. 删除最小值
* heap[1]=heap[size]
* size--
* down(1)
* 4.删除任意一个元素
* heap[k]=heap[size]
* size--
* down(k)
* up(k)
* 5.修改任意一个元素
* heap[k]=x
* down[k]
* up(k)
*/
public class Main {
static int N = 100010;
// size 存放大小
static int size = 0;
// h代表堆
static int[] h = new int[N];
static int[] ph = new int[N];//第k个插入点的下标
static int[] hp = new int[N];//堆里面的第k个点是第几个插入点
public static void main(String[] args){
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
scanner.nextLine();
int m=0;
while (n-->0){
String[] s=scanner.nextLine().split(" ");
String op=s[0];
int k,x;
if(op.equals("I")){
x=Integer.parseInt(s[1]);
++size;
++m;
ph[m]=size;
hp[size]=m;
h[size]=x;
up(size);
}else if(op.equals("PM")){
System.out.println(h[1]);
}else if(op.equals("DM")){
heap_swap(1,size);
size--;
down(1);
}else if(op.equals("D")){
k=Integer.parseInt(s[1]);
k=ph[k];
heap_swap(k,size);
size--;
down(k);
up(k);
}else if(op.equals("C")){
k=Integer.parseInt(s[1]);
x=Integer.parseInt(s[2]);
k=ph[k];
h[k]=x;
down(k);
up(k);
}
}
}
static void up(int u) {
while (u/2>0 && h[u] <h[u/2]){
heap_swap(u,u/2);
u/=2;
}
}
static void down(int u) {
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){
heap_swap(t,u);
down(t);
}
}
// 应用于堆的交换
static void heap_swap(int a, int b) {
swap(ph,hp[a],hp[b]);
swap(hp,a,b);
swap(h,a,b);
}
// 交换数组的两个元素
static void swap(int a[], int x, int y) {
int temp=a[x];
a[x]=a[y];
a[y]=temp;
}
}