博客
关于我
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/

    你可能感兴趣的文章
    ntko web firefox跨浏览器插件_深度比较:2019年6个最好的跨浏览器测试工具
    查看>>
    ntko文件存取错误_苹果推送 macOS 10.15.4:iCloud 云盘文件夹共享终于来了
    查看>>
    Nuget~管理自己的包包
    查看>>
    nullnullHuge Pages
    查看>>
    NumPy 或 Pandas:将数组类型保持为整数,同时具有 NaN 值
    查看>>
    numpy 用法
    查看>>
    Numpy如何使用np.umprod重写range函数中i的python
    查看>>
    oauth2-shiro 添加 redis 实现版本
    查看>>
    OAuth2.0_JWT令牌-生成令牌和校验令牌_Spring Security OAuth2.0认证授权---springcloud工作笔记148
    查看>>
    OAuth2.0_JWT令牌介绍_Spring Security OAuth2.0认证授权---springcloud工作笔记147
    查看>>
    OAuth2.0_介绍_Spring Security OAuth2.0认证授权---springcloud工作笔记137
    查看>>
    OAuth2.0_完善环境配置_把资源微服务客户端信息_授权码存入到数据库_Spring Security OAuth2.0认证授权---springcloud工作笔记149
    查看>>
    OAuth2.0_授权服务配置_Spring Security OAuth2.0认证授权---springcloud工作笔记140
    查看>>
    OAuth2.0_授权服务配置_令牌服务和令牌端点配置_Spring Security OAuth2.0认证授权---springcloud工作笔记143
    查看>>
    OAuth2.0_授权服务配置_客户端详情配置_Spring Security OAuth2.0认证授权---springcloud工作笔记142
    查看>>
    OAuth2.0_授权服务配置_密码模式及其他模式_Spring Security OAuth2.0认证授权---springcloud工作笔记145
    查看>>
    OAuth2.0_授权服务配置_资源服务测试_Spring Security OAuth2.0认证授权---springcloud工作笔记146
    查看>>
    OAuth2.0_环境介绍_授权服务和资源服务_Spring Security OAuth2.0认证授权---springcloud工作笔记138
    查看>>
    OAuth2.0_环境搭建_Spring Security OAuth2.0认证授权---springcloud工作笔记139
    查看>>
    oauth2.0协议介绍,核心概念和角色,工作流程,概念和用途
    查看>>