文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C++基础算法基于哈希表的索引堆变形

2024-04-02 19:55

关注

问题来源

此题来自于Hackerrank中的QHEAP1问题,考查了对堆结构的充分理解。成功完成此题,对最大堆或者最小堆的基本操作实现就没什么太大问题了。

问题简述

实现一个最小堆,对3种类型的输入能给出正确的操作:

注意:题目保证了要删的元素必然是在堆中的,并且在任何时刻,堆中不会有重复的元素。
输入格式:
第1行的值表示共有q个操作,然后再接下来的q行中,每行都有上述3中操作中的任意一种。
比如:

******************输入*******************

1 4 
1 9 

2 4 

******************输出*******************

9

问题分析

对于一个最小堆来说,其满足的性质是只要每个子树中的父亲节点的元素小于其左孩子节点和右孩子节点的元素即可,比如下图所示的这样:

最小堆

图1:最小堆示例图

没错,最小堆根部的元素必然是树中最小的那个元素。除了满足上述的条件之外,最小堆还必须是一颗完全二叉树。也正是由于这个完全二叉树的性质,最小堆是可以用数组来实现的,比如上图的这个最小堆就可以表示成


data = { 5, 8, 20, 10, 35, 12, 50, 15, 16 };

从树结构中不难看出索引之间有关系

这是我们在更新堆信息时最重要的公式,第3个式子的除法是取整的,所以左右孩子都一样。
如果只需要满足操作”1 v”和操作”3”的话,上述这些就已经完全够用了,难点在于这里需要我们对堆中指定的元素进行删除”2 v”。讲道理,这并不是一个最小堆所应该有的操作,最小堆只要管住最小的那个值就好了,其他的结构怎么样,最小堆并不关心。不过,既然题目故意这么出了,要来刁难我们,我们也只能迎难而上了。
借助于索引堆的想法,我们用一个哈希表来记录每一个元素在堆中的索引位置,这样,我们在删除时只需要 O(1) 的复杂度就可以找到要删除的元素了,而删除的过程是 O(log(n)) 的复杂度。
还是以上面那组数据为例,我们希望记录的是如下的信息。


data = { 5, 8, 20, 10, 35, 12, 50, 15, 16 };
mp = {{20, 2}, {35, 4}, {8, 1}, {5, 0}, {16, 8}, {50, 6}, {12, 5}, {10, 3}, {15, 7}};

哈希表中元素的顺序完全无所谓,只要元素中的对应关系正确即可,所以上面的这个是我乱编的,具体的顺序和插入元素的顺序有关系。

代码展示

最后,来展示一下完整的代码,把下面这个代码直接复制粘贴到题目中去Submit是没问题的。


#include <vector>
#include <iostream>
#include <unordered_map>
using namespace std;
class myHeap{
private:
    //作为堆的数组
    vector<int> data;
    //用于存放<元素值,在堆中的索引>的哈希表
    unordered_map<int, int> mp;
    //堆中元素的个数
    int size;
private:
    //上移操作,将元素小的顺着树结构往上移
    void _shiftUp(int index){
        if (index >= size || index < 0)
            return;
        while (index != 0){
            int newIndex = (index - 1) / 2;
            if (data[newIndex] > data[index]){
                //更新哈希表中存放的索引
                mp[data[newIndex]] = index;
                mp[data[index]] = newIndex;
                //更新堆中元素的位置
                swap(data[newIndex], data[index]);
                index = newIndex;
            }
            else
                break;
        }
        return;
    }

    //下移操作,将元素大的顺着树结构往下移
    void _shiftDown(int index){
        if (index >= size || index < 0)
            return;
        while (index * 2 + 1 < size){
            int newIndex = index * 2 + 1;
            //选择左节点和右节点中比较小的那个元素
            if (newIndex + 1 < size && data[newIndex + 1] < data[newIndex])
                newIndex++;
            if (data[newIndex] > data[index])
                break;
            //更新哈希表中存放的索引
            mp[data[newIndex]] = index;
            mp[data[index]] = newIndex;
            //更新堆中元素的位置
            swap(data[newIndex], data[index]);
            index = newIndex;
        }
        return;
    }

public:
    myHeap(){
        size = 0;
    }

    //添加元素
    void add(int d){
        data.push_back(d);
        mp[d] = size++;
        _shiftUp(mp[d]);
    }

    //删除元素
    void del(int d){
        int index = mp[d];
        mp[d] = size - 1;
        mp[data[size - 1]] = index;
        swap(data[index], data[size - 1]);
        size--;
        data.pop_back();
        _shiftUp(index);
        _shiftDown(index);
        mp.erase(d);
    }

    //打印堆中最小值
    void showMin(){
        cout << data[0] << endl;
    }
};

int main() {
    
    int q;
    cin >> q;
    myHeap h;
    for (int i = 0; i < q; i++){
        int index;
        cin >> index;
        if (index == 1){
            int v;
            cin >> v;
            h.add(v);
        }
        else if (index == 2){
            int v;
            cin >> v;
            h.del(v);
        }
        else if (index == 3){
            h.showMin();
        }
    }
}

如有不足,还请指正~

以上就是C++基础算法基于哈希表的索引堆变形的详细内容,更多关于C++算法哈希表索引堆变形的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯