手写堆

  • 手写堆需要支持的操作

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

  • 大根堆和小根堆的特点

  • 存储方式

    • 用一个一维数组来存储
    • 位置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\n", 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;
}

相关题目 堆排序

posted @ 2021-04-17 16:38  呼_呼  阅读(92)  评论(0编辑  收藏  举报