博客
关于我
map + priority_queue实现可以修改任意位置的堆
阅读量:519 次
发布时间:2019-03-07

本文共 1609 字,大约阅读时间需要 5 分钟。

如何实现可修改任意位置的堆?——优先级队列加映射的巧妙结合

在实际编程中,经常需要处理一堆数据,其中任意位置都可能被修改。针对这种需求,传统的优先级队列(priority_queue)并不足够,因为这类数据结构通常只支持通过堆顶提取元素,而无法直接修改堆中的任意位置。为了解决这个问题,我灵感一现,决定将优先级队列与映射结合,通过巧妙的方法实现可修改任意位置的堆。这一方法不仅解决了问题,还在实际应用中表现优异。

手写优先级队列的目的

首先,我没有选择直接使用STL中的优先级队列,而是选择手写一个优先级队列。虽然这可能看起来多此一举,但通过这一过程,我巩固了对优先级队列的理解,并锻炼了自己的编程能力。毕竟,仅仅调用库函数,谁都没有成就感。

结合映射实现可修改性

为了实现可修改任意位置的堆,我想到了将优先级队列与映射(data structure)结合的方法。具体来说,我通过以下几个步骤来实现:

  • 插入操作(I)

    当遇到插入操作时,我首先读取插入的数值x。为了记录每个数的出现次数,我使用了一个映射knuthink。每次插入一个数x,我会将其计数器knuthink[x]加一,并将这个数推入优先级队列q中。同时,我还维护了一个计数器cnt,用来记录已经插入到队列的数据的总数。这一步相对简单,没有特别需要注意的地方。

  • 弹出并返回最小值(PM)

    当处理弹出并返回最小值的操作时,我遇到了一个问题:普通的优先级队列无法多次访问被弹出的元素。因此,我决定先从队列顶部弹出元素x,直到找到一个满足knuthink[x] > 0的值,确保这个x确实存在。然后,我再将x重新推入队列,并输出这个x作为结果。这一方法虽然增加了一些循环,但确保了弹出的元素是有效的。

  • 删除最小值(DM)

    删除操作与弹出操作类似。在弹出队列顶部的元素x时,我同样需要确保knuthink[x] > 0,才能进行删除。如果满足条件,我就直接减少knuthink[x]的计数器。但我发现,用这种方法可能会导致性能问题,因为每次删除都需要进行多次弹出操作。

  • 修改任意位置(D)

    最有意思的是修改操作。我需要修改某个位置k的数值。首先,我减少旧数x的计数器knuthink[x]的值。然后,我找到该位置k,并将ink[k]修改为新的数值y。接着,我增加y的计数器knuthink[y]的值,并重新将y推入队列中。这个操作有点绕,但确保了可以修改任意位置的数值。

  • 解决问题的关键点

    通过以上方法,我解决了几个关键问题:

    • 如何维护数的存在性

      通过使用映射knuthink,我可以实时 track每个数的出现次数。每次进行操作之前,都会先检查该数是否存在。

    • 如何处理重复的数

      我通过将队列中的数推入前,检查其计数器是否为0,确保队列中不会出现重复的数。

    • 如何高效地修改数值

      通过先减少旧数的计数器,再修改ink数组中的值,最后加入新数到队列中,我确保了修改操作的正确性。

    实现的优化思路

    虽然上述方法在理论上是可行的,但在实际应用中可能会遇到一些问题。例如:

    • 队列中可能会积累大量无效的数,我需要添加优化步骤来周期性地清理队列。

    • 在高并发的情况下,队列中的数可能会过于集中,导致性能下降。

    为了应对这些挑战,我计划在未来的开发中引入以下优化:

    • 定期清理队列

      在处理每个操作之前,我会清理队列中无效数的统计信息,以确保队列的高效性。

    • 优化弹出逻辑

      引入优先队列的优化版本,并结合当前的堆信息,优化弹出逻辑。

    • 抖动式优化

      在某些操作中,采用抖动式优化,移除最早加入的无效数。

    总结

    通过将优先级队列与映射结合,我成功实现了可以修改任意位置的堆。这种方法在处理各种操作时都能保持良好的性能,同时也提高了我对数据结构优化能力的认识。这一实现虽然比使用现成的优先级队列复杂了一些,但为后续的项目拆解和优化奠定了坚实的基础。如果有具体的问题,可以在评论区留言,我会尽力解答。

    转载地址:http://lffnz.baihongyu.com/

    你可能感兴趣的文章
    Nginx配置文件nginx.conf中文详解(总结)
    查看>>
    Nginx配置自带的stub状态实现活动监控指标
    查看>>
    nginx配置详解、端口重定向和504
    查看>>
    Nginx配置负载均衡到后台网关集群
    查看>>
    Nginx配置限流,技能拉满!
    查看>>
    Nginx面试三连问:Nginx如何工作?负载均衡策略有哪些?如何限流?
    查看>>
    Nginx:NginxConfig可视化配置工具安装
    查看>>
    ngModelController
    查看>>
    ngrok | 内网穿透,支持 HTTPS、国内访问、静态域名
    查看>>
    ngrok内网穿透可以实现资源共享吗?快解析更加简洁
    查看>>
    NHibernate学习[1]
    查看>>
    NHibernate异常:No persister for的解决办法
    查看>>
    NIFI1.21.0_java.net.SocketException:_Too many open files 打开的文件太多_实际操作---大数据之Nifi工作笔记0051
    查看>>
    NIFI1.21.0_Mysql到Mysql增量CDC同步中_日期类型_以及null数据同步处理补充---大数据之Nifi工作笔记0057
    查看>>
    NIFI1.21.0_Mysql到Mysql增量CDC同步中_补充_更新时如果目标表中不存在记录就改为插入数据_Postgresql_Hbase也适用---大数据之Nifi工作笔记0059
    查看>>
    NIFI1.21.0_NIFI和hadoop蹦了_200G集群磁盘又满了_Jps看不到进程了_Unable to write in /tmp. Aborting----大数据之Nifi工作笔记0052
    查看>>
    NIFI1.21.0最新版本安装_连接phoenix_单机版_Https登录_什么都没改换了最新版本的NIFI可以连接了_气人_实现插入数据到Hbase_实际操作---大数据之Nifi工作笔记0050
    查看>>
    NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_增删改数据分发及删除数据实时同步_通过分页解决变更记录过大问题_02----大数据之Nifi工作笔记0054
    查看>>
    NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表多表增量同步_插入修改删除增量数据实时同步_通过分页解决变更记录过大问题_01----大数据之Nifi工作笔记0053
    查看>>
    NIFI1.21.0通过Postgresql11的CDC逻辑复制槽实现_指定表或全表增量同步_实现指定整库同步_或指定数据表同步配置_04---大数据之Nifi工作笔记0056
    查看>>