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】

  • 相关阅读:
    容器跨主机网络通信学习笔记(以Flannel为例)
    Kubernetes控制器Job和CronJob
    记一次使用Flannel插件排错历程
    Kubernetes控制器Deployment
    Kubernetes如何通过StatefulSet支持有状态应用?
    react18 来了,我 get 到...
    gojs 实用高级用法
    vuecli3 vue2 保留 webpack 支持 vite 成功实践
    calibre 报错 This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem. 解决
    unable to recognize "*.yaml": no matches for kind "RoleBinding" in version "rbac.authorization.k8s.io/v1beta1"
  • 原文地址:https://www.cnblogs.com/siwuxie095/p/6952626.html
Copyright © 2011-2022 走看看