`
eriol
  • 浏览: 400534 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

映射二分堆

阅读更多

引入

 

平常,我们用堆最常见的就是随机地加入元素,随机地取最大值或最小值。这些基本的操作C++中的priority_queue和set都能很好的完成,而且C++中还有一个make_heap,效率较前面2个会更高。而且前面提到的STL都是采用红黑树实现的,很具有稳定性。

 

上面的堆虽然使用简单,但功能上还是有些局限。比如前面提到的堆都只能实现删除最值并没有办法删除指定的值。而且一般STL中的堆都是采用数据存储的,但父亲节点和儿子节点需要交换时,我们需要拷贝所存储的整个数据单元,但数据单元较大时,拷贝的效率就低了。因此,这里介绍一中堆变种,在堆中引入了映射。

 

 

定义

 

具有映射功能的堆称为双向映射堆。又因其常常是在二分堆的基础上实现的,所以也常常叫映射二分堆。

 

 

特点

 

映射二分堆其与普通堆不同的地方是它的节点并不真正保存数据单元本身,而是保存指向数据单元的指针。因此当需要交换父子节点的数据时,我们可以避免拷贝大量数据所消耗的时间。同时,映射二分堆还有一个功能,它可以根据具体的数据单元的索引来删除该单元,即使这个单元不是堆中的最值。

 

 

实现

 

在实现时,我们可以用数字 H[] 存储数据单元,然后采用数组 ind[i]=j 表示 H[i] 存放的是索引号为 j 的数据,mp[j]=i 表示索引索引为 j 的元素存储在 H[i] 中,这样就可以实现双向映射了。

 

(1) 插入堆,我们只需要将插入的元素放在堆尾,然后逐级调整,这个跟普通的二叉堆一样。

 

(2) 删除最值,也跟普通的二叉堆一样,先把堆中最后一个元素与最值对调,然后再调整堆。

 

(3) 删除固定索引的数据单元。我们可以先通过 mp[i],找到其在 H[] 中存放的位置,然后该位置的值跟堆最后一个元素对调,接着从该节点向上调整堆,此时得到的还不是一个正规的堆,还需要重新堆整个堆进行从上到下调整。

 

上面的3中操作中都提到了堆的调整,在调整时我们不需要拷贝数据单元,我们只需交换 ind[] 和 mp[] 2个数组的对应值即可。

 

 

原文地址:http://www.zhongsisi.com/stack-and-mapping/

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics