zoukankan      html  css  js  c++  java
  • 二项堆

    在计算机科学中,二项堆(Binomial Heap)是一种堆结构。与二叉堆(Binary Heap)相比,其优势是可以快速合并两个堆,因此它属于可合并堆(Mergeable Heap)数据结构的一种。

    可合并堆通常支持下面几种操作:

    • Make-Heap():创建并返回一个不包含任何元素的新堆。
    • Insert(H, x):将节点 x 插入到堆 H 中。
    • Minimum(H):返回堆 H 中的最小关键字。
    • Extract-Min(H):将堆 H 中包含最小关键字的节点删除。
    • Union(H1, H2):创建并返回一个包含 H1和 H2 的新堆。
    • Decrease-Key(H, x, k):将新关键字 k 赋给堆 H 中的节点 x。
    • Delete(H, x):从堆 H 中删除 节点 x。

    二项树

    一个二项堆由一组二项树所构成,二项树是一种特殊的多分支有序树,如下图 (a)。

    二项树 Bk 是一种递归定义的有序树。二项树 B0 只包含一个结点。二项树 Bk 由两个子树 Bk-1 连接而成:其中一棵树的根是另一棵树的根的最左孩子。

    二项树的性质有:

    1. 共有 2k 个节点。
    2. 树的高度为 k。
    3. 在深度 d 处恰有  个结点。
    4. 根的度数为 k,它大于任何其他节点的度数;如果根的子女从左到右的编号设为 k-1, k-2, …, 0,子女 i 是子树 Bi 的根。

    上图 (b) 表示二项树 B0 至 B4 中各节点的深度。图 (c) 以另外一种方式来看二项树 Bk

    在一棵包含 n 个节点的二项树中,任意节点的最大度数为 lgn。

    二项堆

    二项堆 H 由一组满足下面的二项堆性质的二项树组成。

    1. H 中的每个二项树遵循最小堆的性质:节点的关键字大于等于其父节点的关键字。
    2. 对于任意非负整数 k,在 H 中至多有一棵二项树的根具有度数 k。

    第一个性质告诉我们,在一棵最小堆有序的二项树中,其根包含了树中最小的关键字。

    第二个性质告诉我们,在包含 n 个节点的二项堆H中,包含至多 floor(lgn)+1 棵二项树。

    比如上图中一个包含 13 个节点的二项堆 H。13的二进制表示为(1101),故 H 包含了最小堆有序二项树B3,B2 和 B0, 他们分别有 8,4 和 1 个节点,即共有 13 个节点。

    代码示例

      1 /* heap.h -- Binomial Heaps
      2  *
      3  * Copyright (c) 2008, Bjoern B. Brandenburg <bbb [at] cs.unc.edu>
      4  *
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions are met:
      9  *     * Redistributions of source code must retain the above copyright
     10  *       notice, this list of conditions and the following disclaimer.
     11  *     * Redistributions in binary form must reproduce the above copyright
     12  *       notice, this list of conditions and the following disclaimer in the
     13  *       documentation and/or other materials provided with the distribution.
     14  *     * Neither the name of the University of North Carolina nor the
     15  *       names of its contributors may be used to endorse or promote products
     16  *       derived from this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY  COPYRIGHT OWNER AND CONTRIBUTERS ``AS IS'' AND
     19  * ANY  EXPRESS OR  IMPLIED  WARRANTIES,  INCLUDING, BUT  NOT  LIMITED TO,  THE
     20  * IMPLIED WARRANTIES  OF MERCHANTABILITY AND FITNESS FOR  A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED.  IN NO  EVENT SHALL THE  COPYRIGHT OWNER OR  CONTRIBUTERS BE
     22  * LIABLE  FOR  ANY  DIRECT,   INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
     23  * CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT  LIMITED  TO,  PROCUREMENT  OF
     24  * SUBSTITUTE GOODS  OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
     25  * INTERRUPTION)  HOWEVER CAUSED  AND ON  ANY THEORY  OF LIABILITY,  WHETHER IN
     26  * CONTRACT,  STRICT LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE OR  OTHERWISE)
     27  * ARISING IN ANY WAY  OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
     28  * POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #ifndef HEAP_H
     32 #define HEAP_H
     33 
     34 #define NOT_IN_HEAP UINT_MAX
     35 
     36 struct heap_node {
     37     struct heap_node*     parent;
     38     struct heap_node*     next;
     39     struct heap_node*     child;
     40 
     41     unsigned int         degree;
     42     void*            value;
     43     struct heap_node**    ref;
     44 };
     45 
     46 struct heap {
     47     struct heap_node*     head;
     48     /* We cache the minimum of the heap.
     49      * This speeds up repeated peek operations.
     50      */
     51     struct heap_node*    min;
     52 };
     53 
     54 /* item comparison function:
     55  * return 1 if a has higher prio than b, 0 otherwise
     56  */
     57 typedef int (*heap_prio_t)(struct heap_node* a, struct heap_node* b);
     58 
     59 static inline void heap_init(struct heap* heap)
     60 {
     61     heap->head = NULL;
     62     heap->min  = NULL;
     63 }
     64 
     65 static inline void heap_node_init_ref(struct heap_node** _h, void* value)
     66 {
     67     struct heap_node* h = *_h;
     68     h->parent = NULL;
     69     h->next   = NULL;
     70     h->child  = NULL;
     71     h->degree = NOT_IN_HEAP;
     72     h->value  = value;
     73     h->ref    = _h;
     74 }
     75 
     76 static inline void heap_node_init(struct heap_node* h, void* value)
     77 {
     78     h->parent = NULL;
     79     h->next   = NULL;
     80     h->child  = NULL;
     81     h->degree = NOT_IN_HEAP;
     82     h->value  = value;
     83     h->ref    = NULL;
     84 }
     85 
     86 static inline void* heap_node_value(struct heap_node* h)
     87 {
     88     return h->value;
     89 }
     90 
     91 static inline int heap_node_in_heap(struct heap_node* h)
     92 {
     93     return h->degree != NOT_IN_HEAP;
     94 }
     95 
     96 static inline int heap_empty(struct heap* heap)
     97 {
     98     return heap->head == NULL && heap->min == NULL;
     99 }
    100 
    101 /* make child a subtree of root */
    102 static inline void __heap_link(struct heap_node* root,
    103                    struct heap_node* child)
    104 {
    105     child->parent = root;
    106     child->next   = root->child;
    107     root->child   = child;
    108     root->degree++;
    109 }
    110 
    111 /* merge root lists */
    112 static inline struct heap_node* __heap_merge(struct heap_node* a,
    113                          struct heap_node* b)
    114 {
    115     struct heap_node* head = NULL;
    116     struct heap_node** pos = &head;
    117 
    118     while (a && b) {
    119         if (a->degree < b->degree) {
    120             *pos = a;
    121             a = a->next;
    122         } else {
    123             *pos = b;
    124             b = b->next;
    125         }
    126         pos = &(*pos)->next;
    127     }
    128     if (a)
    129         *pos = a;
    130     else
    131         *pos = b;
    132     return head;
    133 }
    134 
    135 /* reverse a linked list of nodes. also clears parent pointer */
    136 static inline struct heap_node* __heap_reverse(struct heap_node* h)
    137 {
    138     struct heap_node* tail = NULL;
    139     struct heap_node* next;
    140 
    141     if (!h)
    142         return h;
    143 
    144     h->parent = NULL;
    145     while (h->next) {
    146         next    = h->next;
    147         h->next = tail;
    148         tail    = h;
    149         h       = next;
    150         h->parent = NULL;
    151     }
    152     h->next = tail;
    153     return h;
    154 }
    155 
    156 static inline void __heap_min(heap_prio_t higher_prio, struct heap* heap,
    157                   struct heap_node** prev, struct heap_node** node)
    158 {
    159     struct heap_node *_prev, *cur;
    160     *prev = NULL;
    161 
    162     if (!heap->head) {
    163         *node = NULL;
    164         return;
    165     }
    166 
    167     *node = heap->head;
    168     _prev = heap->head;
    169     cur   = heap->head->next;
    170     while (cur) {
    171         if (higher_prio(cur, *node)) {
    172             *node = cur;
    173             *prev = _prev;
    174         }
    175         _prev = cur;
    176         cur   = cur->next;
    177     }
    178 }
    179 
    180 static inline void __heap_union(heap_prio_t higher_prio, struct heap* heap,
    181                 struct heap_node* h2)
    182 {
    183     struct heap_node* h1;
    184     struct heap_node *prev, *x, *next;
    185     if (!h2)
    186         return;
    187     h1 = heap->head;
    188     if (!h1) {
    189         heap->head = h2;
    190         return;
    191     }
    192     h1 = __heap_merge(h1, h2);
    193     prev = NULL;
    194     x    = h1;
    195     next = x->next;
    196     while (next) {
    197         if (x->degree != next->degree ||
    198             (next->next && next->next->degree == x->degree)) {
    199             /* nothing to do, advance */
    200             prev = x;
    201             x    = next;
    202         } else if (higher_prio(x, next)) {
    203             /* x becomes the root of next */
    204             x->next = next->next;
    205             __heap_link(x, next);
    206         } else {
    207             /* next becomes the root of x */
    208             if (prev)
    209                 prev->next = next;
    210             else
    211                 h1 = next;
    212             __heap_link(next, x);
    213             x = next;
    214         }
    215         next = x->next;
    216     }
    217     heap->head = h1;
    218 }
    219 
    220 static inline struct heap_node* __heap_extract_min(heap_prio_t higher_prio,
    221                            struct heap* heap)
    222 {
    223     struct heap_node *prev, *node;
    224     __heap_min(higher_prio, heap, &prev, &node);
    225     if (!node)
    226         return NULL;
    227     if (prev)
    228         prev->next = node->next;
    229     else
    230         heap->head = node->next;
    231     __heap_union(higher_prio, heap, __heap_reverse(node->child));
    232     return node;
    233 }
    234 
    235 /* insert (and reinitialize) a node into the heap */
    236 static inline void heap_insert(heap_prio_t higher_prio, struct heap* heap,
    237                    struct heap_node* node)
    238 {
    239     struct heap_node *min;
    240     node->child  = NULL;
    241     node->parent = NULL;
    242     node->next   = NULL;
    243     node->degree = 0;
    244     if (heap->min && higher_prio(node, heap->min)) {
    245         /* swap min cache */
    246         min = heap->min;
    247         min->child  = NULL;
    248         min->parent = NULL;
    249         min->next   = NULL;
    250         min->degree = 0;
    251         __heap_union(higher_prio, heap, min);
    252         heap->min   = node;
    253     } else
    254         __heap_union(higher_prio, heap, node);
    255 }
    256 
    257 static inline void __uncache_min(heap_prio_t higher_prio, struct heap* heap)
    258 {
    259     struct heap_node* min;
    260     if (heap->min) {
    261         min = heap->min;
    262         heap->min = NULL;
    263         heap_insert(higher_prio, heap, min);
    264     }
    265 }
    266 
    267 /* merge addition into target */
    268 static inline void heap_union(heap_prio_t higher_prio,
    269                   struct heap* target, struct heap* addition)
    270 {
    271     /* first insert any cached minima, if necessary */
    272     __uncache_min(higher_prio, target);
    273     __uncache_min(higher_prio, addition);
    274     __heap_union(higher_prio, target, addition->head);
    275     /* this is a destructive merge */
    276     addition->head = NULL;
    277 }
    278 
    279 static inline struct heap_node* heap_peek(heap_prio_t higher_prio,
    280                       struct heap* heap)
    281 {
    282     if (!heap->min)
    283         heap->min = __heap_extract_min(higher_prio, heap);
    284     return heap->min;
    285 }
    286 
    287 static inline struct heap_node* heap_take(heap_prio_t higher_prio,
    288                       struct heap* heap)
    289 {
    290     struct heap_node *node;
    291     if (!heap->min)
    292         heap->min = __heap_extract_min(higher_prio, heap);
    293     node = heap->min;
    294     heap->min = NULL;
    295     if (node)
    296         node->degree = NOT_IN_HEAP;
    297     return node;
    298 }
    299 
    300 static inline void heap_decrease(heap_prio_t higher_prio, struct heap* heap,
    301                  struct heap_node* node)
    302 {
    303     struct heap_node *parent;
    304     struct heap_node** tmp_ref;
    305     void* tmp;
    306 
    307     /* node's priority was decreased, we need to update its position */
    308     if (!node->ref)
    309         return;
    310     if (heap->min != node) {
    311         if (heap->min && higher_prio(node, heap->min))
    312             __uncache_min(higher_prio, heap);
    313         /* bubble up */
    314         parent = node->parent;
    315         while (parent && higher_prio(node, parent)) {
    316             /* swap parent and node */
    317             tmp           = parent->value;
    318             parent->value = node->value;
    319             node->value   = tmp;
    320             /* swap references */
    321             if (parent->ref)
    322                 *(parent->ref) = node;
    323             *(node->ref)   = parent;
    324             tmp_ref        = parent->ref;
    325             parent->ref    = node->ref;
    326             node->ref      = tmp_ref;
    327             /* step up */
    328             node   = parent;
    329             parent = node->parent;
    330         }
    331     }
    332 }
    333 
    334 static inline void heap_delete(heap_prio_t higher_prio, struct heap* heap,
    335                    struct heap_node* node)
    336 {
    337     struct heap_node *parent, *prev, *pos;
    338     struct heap_node** tmp_ref;
    339     void* tmp;
    340 
    341     if (!node->ref) /* can only delete if we have a reference */
    342         return;
    343     if (heap->min != node) {
    344         /* bubble up */
    345         parent = node->parent;
    346         while (parent) {
    347             /* swap parent and node */
    348             tmp           = parent->value;
    349             parent->value = node->value;
    350             node->value   = tmp;
    351             /* swap references */
    352             if (parent->ref)
    353                 *(parent->ref) = node;
    354             *(node->ref)   = parent;
    355             tmp_ref        = parent->ref;
    356             parent->ref    = node->ref;
    357             node->ref      = tmp_ref;
    358             /* step up */
    359             node   = parent;
    360             parent = node->parent;
    361         }
    362         /* now delete:
    363          * first find prev */
    364         prev = NULL;
    365         pos  = heap->head;
    366         while (pos != node) {
    367             prev = pos;
    368             pos  = pos->next;
    369         }
    370         /* we have prev, now remove node */
    371         if (prev)
    372             prev->next = node->next;
    373         else
    374             heap->head = node->next;
    375         __heap_union(higher_prio, heap, __heap_reverse(node->child));
    376     } else
    377         heap->min = NULL;
    378     node->degree = NOT_IN_HEAP;
    379 }
    380 
    381 #endif /* HEAP_H */

    参考资料

  • 相关阅读:
    PostgreSQL学习手册(五) 函数和操作符
    数据表的左连接与右连接
    ESX虚拟机文件列表详解
    程序员生存定律-打造属于自己的稀缺性
    C语言字符串处理函数
    托福听力
    DNS map file in windows
    Ubuntu 下安装VNC server
    PostgreSQL 数据库错误状态编号解释[附带列表
    [留学新生须知]新生美国生活常用单词汇总
  • 原文地址:https://www.cnblogs.com/gaochundong/p/binomial_heap.html
Copyright © 2011-2022 走看看