zoukankan      html  css  js  c++  java
  • 堆 续9

    -----------------siwuxie095

       

       

       

       

       

       

       

       

    和堆相关的问题

       

       

    1)使用堆实现优先队列:动态选择优先级最高的任务执行

       

       

    完全可以使用堆当做一个优先队列,对于系统的若干个进程来讲,

    每次都用堆找到优先级最高的任务进行执行,而如果系统来了新

    的任务,只要把这个任务插入到堆中即可,如果操作系统要修改

    任务的优先级,也是可以实现的

       

       

       

       

       

    2)游戏中角色的人工智能

       

       

    游戏中的某个角色要自动选择攻击范围里的敌人进行攻击,它要

    根据这些敌人的属性选择最需要攻击的那个敌人进行攻击。在这

    个过程中,就可以把在攻击范围中的敌人放进一个堆中,由堆来

    选出每次要攻击哪个敌人。如果有新的敌人进入了攻击范围,就

    把新的敌人插入到堆中即可

       

    不难看出,所谓很智能的决策过程,其实背后就是一个数据结构,

    使用一个堆就可以表现出不错的智能来

       

       

       

       

       

    3)在 1000000 个元素中选出前 100

       

       

    如果将这一百万个元素都排一遍序,就是 n*lgn 这样的复杂度,

    但完全可以使用一个最小堆,保持最小堆中元素的数量永远是

    小于等于 100

       

    这样一来,当把前 100 个元素放进这个最小堆之后,每次新放

    入一个元素,就会将堆中当前最小的元素移出去,这样就维持

    整个堆一直保持着 100 个元素。当把这一百万个元素全都遍历

    完成后,最终这个最小堆中所存放的所有元素,就是这一百万

    个元素中的前一百名

       

    这样,算法的时间复杂度就变成了 n*lgm 级别的

       

       

       

       

       

    4)多路归并排序(k 路归并排序):可以使用堆实现多路的归并

       

       

    普通归并排序:在归并排序的过程将当前要处理的数组,一分为二,

    分别排序以后再进行归并。归并时,每次只要比较两个子数组的第

    一个元素的大小即可

       

    多路归并排序:在归并排序的过程中将整个数组分成两个以上的子

    数组,之后再进行归并

       

       

    假如分成了四部分,那么在归并的过程中,每次就要比较四个元素

    的大小关系,在比较四个元素的大小关系时怎么比更快呢?

       

    可以逐一比较,不过一个更好的方法是将这四个元素,放进一个

    小堆中,每次从堆中推出一个当前最小的元素,推出的这个元素属

    于哪个子数组,就从这个子数组中再拿出一个新的元素添加进堆中

       

       

    更一般的,对于一个有 n 个元素的数组,做一个 k 路的归并排序

       

    k 路归并排序的 k 的选择,实际上是一个性能平衡。k 越大,层

    数就会越小,但在每次归并的过程中需要比较的元素也就越多

       

    「k 随测试用例的不同而变化」

       

    如果 n 个元素的数组要做 n 路的归并排序,那么归并的过程只需

    要递归一层即可

       

    在这一层中每一个子数组中都只有一个元素,剩下的事情就是使

    用一个堆,将这 n 个只有一个元素的子数组进行排序

       

    此时,归并排序退化成了堆排序

       

       

       

       

       

    5)多叉堆(d 叉堆)

       

       

    二叉堆是每一个节点最多只能有两个孩子,那么 d 叉堆就是每个

    节点最多只能有 d 个孩子

       

       

    d 叉堆的 d 的选择,也是一个性能上的平衡。d 越大,层数越小,

    但在 Shift Up 和 Shift Down 的过程中,需要比较的元素也就越

    「d 随测试用例的不同而变化」

       

    显然,二叉堆最经典,且在一般的任务中,二叉堆足以应付

       

       

       

       

       

    6)堆的实现细节优化

       

       

    1)Shift Up 和 Shift Down 的过程中,使用赋值操作代替交换操作

       

    2)索引从 0 开始

       

    3)没有 capacity 的限制,动态调整堆中数组的大小

       

    注意:当 capacity 不够用了,重新申请空间的过程一定是复杂度为

    O(n) 级别的算法,且要申请 2*capacity 这么大的空间

       

    这样一来,从平均效率来讲,堆中的所有的操作依然是保持不变的,

    不会因为这个动态的调整,而对用户使用这个堆的性能产生巨大的

    影响

       

       

       

       

       

    7)最大最小队列

       

       

    最大堆和最小堆所形成的这个优先队列,要么可以非常容易的找到

    所有元素中最大的元素,要么可以非常容易的找到所有元素中最小

    的元素

       

    其实可以设计一个类,叫做 最大最小队列,既能非常快的找到最大

    的元素,又能非常快的找到最小的元素

       

    具体实现:可以在这个数据结构中,既放一个最大堆,又放一个最

    小堆,两个堆同时维护同一组数据

       

       

       

       

       

    8)二项堆、斐波那契堆

       

       

    其实堆还有很多的变种,如:二项堆斐波那契堆

       

    这些堆,或者它们的操作速度更快一些,或者在一些特殊的场合,

    对于一些特殊的操作有更高的性能优势

       

       

       

       

       

       

       

       

    【made by siwuxie095】

  • 相关阅读:
    Sendkeys 和 Sendmessage 使用技巧一例
    和菜鸟一起学算法之二分法求极值问题
    和菜鸟一起学算法之三分法求极值问题
    和菜鸟一起学证券投资之国内生产总值GDP
    和菜鸟一起学OK6410之Led字符驱动
    和菜鸟一起学OK6410之最简单驱动模块hello world
    和菜鸟一起学OK6410之交叉编译hello world
    和菜鸟一起学android4.0.3源码之touchscreen配置+调试记录
    和菜鸟一起学android4.0.3源码之红外遥控器适配
    和菜鸟一起学OK6410之最简单字符驱动
  • 原文地址:https://www.cnblogs.com/siwuxie095/p/6952626.html
Copyright © 2011-2022 走看看