• 手写堆


    • 手写堆需要支持的操作

      • 插入一个数
      • 求集合当中的最小值
      • 删除最小值
      • 删除任意一个元素
      • 修改任意一个元素
    • 堆是一棵完全二叉树

    • 大根堆和小根堆的特点

    • 存储方式

      • 用一个一维数组来存储
      • 位置1存储根节点(下标从0开始需要特殊出根节点,因为0 * 2 == 0)
      • 对于节点x,左儿子的下标为2x,右儿子的下标为2x++1
    • 堆支持两个基本的操作,这两个基本操作可以组合出前面提出的操作

      • down()
      • up()
    • 以小根堆为例,如果将某个节点的值变大,为了维护小根堆的性质,需要将当前节点"下沉"几次,直到整棵树满足小根堆的性质;如果将某个节点的值变小,需要将当前节点“上浮”几次,直到整棵树重新满足最小堆的性质

    • 用两个基本操作模拟对一个堆可以进行的操作(以小顶堆为例)

      • heap[++ size] = x; up(size);
      • heap[1];
      • heap[1] = heap[size]; size --; down(1);
      • heap[k] = heap[size]; size --; up(k) 或 down[k]
      • heap[k] = x; down[x] 或 up[x];

    模拟堆

    #include <iostream>
    #include <algorithm>
    #include <string.h> //使用strcmp必须包含这个头文件
      
    using namespace std;
    
    const int N = 100010;
    
    int h[N], ph[N], hp[N], h_size; //ph存储第k个插入点的下标j,hp存储的是下标为j的元素是第k个插入的点,互为反映射
    
    void heap_swap(int a, int b) {
        swap(ph[hp[a]], ph[hp[b]]);
        swap(hp[a], hp[b]);
        swap(h[a], h[b]);
    }//为了实现操作4和操作5而定义的特殊的swap操作,大多数情况下不需要实现这些复杂的交换操作
    
    void down(int u) {
        int t = u;
        if(u * 2 <= h_size && h[u * 2] < h[t]) t = u * 2;
        if(u * 2 + 1 <= h_size && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
        if(u != t) {
            heap_swap(u, t);
            down(t);
        }
    }
    
    void up(int u) {
        while(u / 2 && h[u / 2] > h[u]) {
            heap_swap(u / 2, u);
            u /= 2;
        }
    }
    
    int main() {
        int n, m = 0;
        scanf("%d", &n); 
        
        while(n -- ) {
            char op[10];
            int k, x;
            scanf("%s", op);
            
            if (!strcmp(op, "I")) {
                scanf("%d", &x);
                h_size ++ ;
                m ++ ;
                ph[m] = h_size; hp[h_size] = m;
                h[h_size] = x;
                up(h_size);
            }
            else if (!strcmp(op, "PM")) printf("%d
    ", h[1]);
            else if (!strcmp(op, "DM")) {
                heap_swap(1, h_size);
                h_size -- ;
                down(1);
            }
            else if (!strcmp(op, "D")) {
                scanf("%d", &k);
                k = ph[k];
                heap_swap(k, h_size);
                h_size -- ;
                down(k), up(k);
            }
            else {
                scanf("%d%d", &k, &x);
                k = ph[k];
                h[k] = x;
                down(k), up(k);
            }
        }
        
        return 0;
    }
    

    相关题目 堆排序

  • 相关阅读:
    rpcbind禁用不了,111端口无法释放?
    python3 pexpect 自动交互修改linux系统密码
    pip将包安装到指定位置
    使用openssl对文件进行加密解密
    james-2.3.2.1发邮件慢,不能多线程同时发
    java指令执行一个class文件并指定依赖包的路径
    ltib for imx280 tips
    使用net-snmp的snmptranslate命令验证MIB文件
    嵌入式linux去掉开机进度条,更换背景,换企鹅logo
    使用cppcheck对C代码进行静态检查
  • 原文地址:https://www.cnblogs.com/huhu555/p/14671127.html
Copyright © 2020-2023  润新知