公告

👇 微信 👇

图片

欢迎私信交流

Skip to content

10-堆 ​

算法思想 ​

堆 ​

  • 堆是满足一些条件的完全二叉树

算法模板 ​

java
import java.util.*;
public class Main {
    static int N = 100010;
    static int[] h = new int[N],    
    // hp[i](heap -> point)存储堆中第 i 元素的插入序号(第 k 个插入)
    // hp 记录每个元素的插入序号
    hp = new int[N],
    // ph[i](point -> heap)存储第 i 个插入的元素在堆中的索引
    ph = new int[N];
    // 为什么有了 hp 还需要 ph
    // 便于根据插入序号(k)查找堆中对应元素,否则需要遍历整个堆
    
    // cnt 代表堆中元素的总数
    // m 代表最小的未使用的插入序号(从1开始)
    static int cnt, m;


    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();

        while(n -- > 0)
        {
            String s = in.next();
            int k, x;
            if(s.equals("I"))
            {
                x = in.nextInt();
                m ++;
                cnt ++;
                ph[m] = cnt;
                hp[cnt] = m;

                h[cnt] = x;
                up(cnt);
            }
            else if(s.equals("PM"))
            {
                System.out.println(h[1]);
            }
            else if(s.equals("DM"))
            {
                heap_swap(1, cnt);
                cnt --;
                down(1);
            }
            else if(s.equals("D"))
            {
                k = in.nextInt();
                int index = ph[k];

                heap_swap(index, cnt);
                cnt --;
                // 堆中的任一元素的值发生变化后,
                // 可能需要上移或下坠。
                // 此处调用直接调用两个方法,
                // 但是只会执行其中一个方法,
                // 另一个方法会因为条件不满足而直接退出
                up(index);
                down(index);
            }            
            else if(s.equals("C"))
            {
                k = in.nextInt();
                x = in.nextInt();
                // 第 k 个插入的元素在堆中的索引
                int index = ph[k];

                h[index] = x;
                up(index);
                down(index);
            }
        }
    }

    static void up(int u)
    {
        while(u / 2 > 0 && h[u] < h[u / 2])
        {
            heap_swap(u, u / 2);
            u >>= 1;
        }
    }

    static void down(int u)
    {
        int t = u;
        if(u * 2 <= cnt && h[u * 2] < h[t]) t = u * 2;
        if(u * 2 + 1 <= cnt && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
        if(t != u)
        {
            heap_swap(t, u);
            down(t);
        }
    }

    // 堆中元素的索引 i, j
    static void heap_swap(int i, int j)
    {   // 堆中元素的插入序号
        int k1 = hp[i], k2 = hp[j];

        swap(ph, k1, k2);
        swap(hp, i, j);
        swap(h, i, j);
    }

    static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}