Fork me on GitHub

堆 续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】

posted on 2017-06-06 17:20  siwuxie095  阅读(140)  评论(0编辑  收藏  举报

导航