栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

算法与数据结构—模拟堆

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

算法与数据结构—模拟堆

算法与数据结构—模拟堆 strcmp函数

C/C++函数,比较两个字符串
设这两个字符串为str1,str2,
若str1=str2,则返回零;
若str1 若str1>str2,则返回正数。
头文件:string.h

例题

维护一个集合,初始时集合为空,支持如下几种操作:
I x,插入一个数 x;
PM,输出当前集合中的最小值;
DM,删除当前集合中的最小值(数据保证此时的最小值唯一);
D k,删除第 k 个插入的数;
C k x,修改第 k 个插入的数,将其变为 x;
现在要进行 N 次操作,对于所有第 2 个操作,输出当前集合的最小值。
输入格式
第一行包含整数 N。
接下来 N 行,每行包含一个操作指令,操作指令为 I x,PM,DM,D k 或 C k x 中的一种。
数据范围
1≤N≤1e5
−1e9≤x≤1e9

首先建立三个数组hp,ph,h
const int N=100010;
int h[N], ph[N], hp[N], cnt;
这里的cnt指的是下标到第几个位置了
h数组用来存储插入的值
如何理解hp和ph数组

首先需要理解的是hp和ph这两个数组到底存的是啥,到底有啥作用,如果不建立这两个数组为什么不行?
hp是heap pointer的缩写,表示堆数组中下标到第k个插入的映射
ph是pointer heap的缩写,表示第k个插入到堆数组中的下标的映射
hp和ph数组是互为反函数的

插入

在堆这个数据结构中,数据的插入都是插入到堆尾,然后再up的。

//代码如下
if (!strcmp(op, "I"))
        {
            scanf("%d", &x);
            cnt ++ ;
            m ++ ;//记录第几次插入
            ph[m] = cnt, hp[cnt] = m;//每次插入都是在堆尾插入
            h[cnt] = x;//记录插入的值
            up(cnt);
        }

这里暂时没有体现出hp和ph的作用

删除集合中的最小值

先将第一个元素与最后一个元素进行位置互换,然后删除最后一个元素,再将第一个元素down下去

if (!strcmp(op, "DM"))
        {
            heap_swap(1, cnt);
            cnt -- ;
            down(1);

在删除第k个插入元素的操作中,我们首先得知道第k个插入元素在堆数组中的什么位置,即堆数组下标是啥。
很显然,用一个ph数组来存储会方便查找。这样我们就知道了第k个插入的元素在哪了。然后我们需要做的是和堆尾元素交换,最后再在原来第k个元素所在的位置进行down和up操作。
由于交换完后ph[k]的值变了,为ph[cnt]了,所以必须要在之前保存ph[k]的值,不然无法进行down和up操作。

删除第k个插入的数
if (!strcmp(op, "D"))
        {
            scanf("%d", &k);
            k = ph[k];
            heap_swap(k, cnt);
            cnt -- ;
            up(k);
            down(k);
        }
修改第k个插入的数
if(!strcmp(op, "C")){
            scanf("%d%d", &k, &x);
            k = ph[k];
            h[k] = x;
            up(k);
            down(k);
        }

似乎有了ph数组就可以完成所有操作了,但为什么还要有一个hp数组呢?
原因就在于在swap操作中我们输入是堆数组的下标,无法知道每个堆数组的下标对应的是第几个插入的元素。
所以需要hp数组方便查找
明白了这些也不难理解heap_swap函数啦

heap_swap函数的实现
void heap_swap(int a, int b)
{
    swap(ph[hp[a]],ph[hp[b]]);
    swap(hp[a], hp[b]);
    swap(h[a], h[b]);
}
完整代码
#include 
#include 
#include 

using namespace std;

const int N = 100010;

int h[N], ph[N], hp[N], cnt;

void heap_swap(int a, int b)
{
    swap(ph[hp[a]],ph[hp[b]]);
    swap(hp[a], hp[b]);
    swap(h[a], h[b]);
}

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 (u != t)
    {
        heap_swap(u, t);
        down(t);
    }
}

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

int main()
{
    int n, m = 0;
    scanf("%d", &n);
    while (n -- )
    {
        char op[5];
        int k, x;
        scanf("%s", op);
        if (!strcmp(op, "I"))
        {
            scanf("%d", &x);
            cnt ++ ;
            m ++ ;
            ph[m] = cnt, hp[cnt] = m;
            h[cnt] = x;
            up(cnt);
        }
        else if (!strcmp(op, "PM")) printf("%dn", h[1]);
        else if (!strcmp(op, "DM"))
        {
            heap_swap(1, cnt);
            cnt -- ;
            down(1);
        }
        else if (!strcmp(op, "D"))
        {
            scanf("%d", &k);
            k = ph[k];
            heap_swap(k, cnt);
            cnt -- ;
            up(k);
            down(k);
        }
        else
        {
            scanf("%d%d", &k, &x);
            k = ph[k];
            h[k] = x;
            up(k);
            down(k);
        }
    }

    return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/457513.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号