zoukankan      html  css  js  c++  java
  • pop_heap算法 (将根节点置于容器尾部后重调heap结构)

    算法描述

    置根节点于容器尾部,并调整heap结构使其满足max-heap.

    算法的核心是根节点为空洞后heap结构的调整,而不是取最大值(最大值就是根节点)!

    根节点为空洞后,为了满足max-heap结构,要割舍最下层最右边的叶节点,重新安插它的位置,即调整heap结构。

    注:根节点即最大元素只是被置放于底部容器的最尾端,尚未被取走,可通过back()操作取其值,可通过pop_back()操作移除。

    如何重新调整结构呢?

    根节点为空洞后,执行percolate down(下溯)程序:将空洞节点和其较大子节点对调,并持续下放,直到叶节点为止。

    然后将被割舍的节点至于“已达到叶层的空洞节点”,再对它进行一次percolate up(上溯)程序,即可。

     
     
     
     
     
     
     
    // 下面的result就是根节点!并未被取走。
    // 以下這組 __pop_heap() 不允許指定「大小比較標準」
    template <class RandomAccessIterator, class T, class Distance>
    inline void __pop_heap(RandomAccessIterator first, RandomAccessIterator last,
                           RandomAccessIterator result, T value, Distance*) {
      *result = *first; // 設定尾值為首值,於是尾值即為欲求結果,
                           // 可由客端稍後再以底層容器之 pop_back() 取出尾值。
      __adjust_heap(first, Distance(0), Distance(last - first), value);
      // 以上欲重新調整 heap,洞號為 0(亦即樹根處),欲調整值為 value(原尾值)。
    }
    
    template <class RandomAccessIterator, class T>
    inline void __pop_heap_aux(RandomAccessIterator first,
                               RandomAccessIterator last, T*) {
      __pop_heap(first, last-1, last-1, T(*(last-1)), distance_type(first));
      // 以上,根據 implicit representation heap 的次序特性,pop動作的結果
      // 應為底層容器的第一個元素。因此,首先設定欲調整值為尾值,然後將首值調至 
      // 尾節點(所以以上將迭代器result設為last-1)。然後重整 [first, last-1),
      // 使之重新成一個合格的 heap。
    }
    


     

    /*下面才是算法核心*/

    根节点为空洞后,执行percolate down(下溯)程序:将空洞节点和其较大子节点对调,并持续下放,直到叶节点为止。

    然后将被割舍的节点至于“已达到叶层的空洞节点”,再对它进行一次percolate up(上溯)程序,即可。

    void __adjust_heap(RandomAccessIterator first, Distance holeIndex,
                       Distance len, T value) {
      Distance topIndex = holeIndex;
      Distance secondChild = 2 * holeIndex + 2;	// 洞節點之右子節點
      while (secondChild < len) {
        // 比較洞節點之左右兩個子值,然後以 secondChild 代表較大子節點。
        if (*(first + secondChild) < *(first + (secondChild - 1)))
          secondChild--;   
        // Percolate down:令較大子值為洞值,再令洞號下移至較大子節點處。
        *(first + holeIndex) = *(first + secondChild);  
        holeIndex = secondChild;
        // 找出新洞節點的右子節點
        secondChild = 2 * (secondChild + 1);
      }
      if (secondChild == len) { // 沒有右子節點,只有左子節點
        // Percolate down:令左子值為洞值,再令洞號下移至左子節點處。
        *(first + holeIndex) = *(first + (secondChild - 1));
        holeIndex = secondChild - 1;
      }
      // 將欲調整值填入目前的洞號內。注意,此時肯定滿足次序特性。
      // 依侯捷之見,下面直接改為 *(first + holeIndex) = value; 應該可以。
      // fys:侯捷说直接改是不可以的,在侯捷新书里澄清了此处。
      __push_heap(first, holeIndex, topIndex, value);
    }
    
  • 相关阅读:
    SQL GUID和自增列做主键的优缺点
    python __future__ 的几种特性
    数据库中文乱码处理
    Android_Intent意图详解
    Windows Server 2012 R2超级虚拟化之六 Hyper-v Replica 2.0和Live migrations
    如今网站定位,需立足于用户
    Hibernate 数据的批量插入、更新和删除
    paip.提升用户体验---论文本编辑器的色彩方案
    时间管理方法学习
    网站优化:从搜索引擎到社交网络的艰难转变
  • 原文地址:https://www.cnblogs.com/helloweworld/p/2846216.html
Copyright © 2011-2022 走看看