Home | History | Annotate | Line # | Download | only in src
      1 /* Copyright (c) 2013, Ben Noordhuis <info (at) bnoordhuis.nl>
      2  *
      3  * Permission to use, copy, modify, and/or distribute this software for any
      4  * purpose with or without fee is hereby granted, provided that the above
      5  * copyright notice and this permission notice appear in all copies.
      6  *
      7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     10  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     12  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     13  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     14  */
     15 
     16 #ifndef UV_SRC_HEAP_H_
     17 #define UV_SRC_HEAP_H_
     18 
     19 #include <stddef.h>  /* NULL */
     20 
     21 #if defined(__GNUC__)
     22 # define HEAP_EXPORT(declaration) __attribute__((unused)) static declaration
     23 #else
     24 # define HEAP_EXPORT(declaration) static declaration
     25 #endif
     26 
     27 struct heap_node {
     28   struct heap_node* left;
     29   struct heap_node* right;
     30   struct heap_node* parent;
     31 };
     32 
     33 /* A binary min heap.  The usual properties hold: the root is the lowest
     34  * element in the set, the height of the tree is at most log2(nodes) and
     35  * it's always a complete binary tree.
     36  *
     37  * The heap function try hard to detect corrupted tree nodes at the cost
     38  * of a minor reduction in performance.  Compile with -DNDEBUG to disable.
     39  */
     40 struct heap {
     41   struct heap_node* min;
     42   unsigned int nelts;
     43 };
     44 
     45 /* Return non-zero if a < b. */
     46 typedef int (*heap_compare_fn)(const struct heap_node* a,
     47                                const struct heap_node* b);
     48 
     49 /* Public functions. */
     50 HEAP_EXPORT(void heap_init(struct heap* heap));
     51 HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap));
     52 HEAP_EXPORT(void heap_insert(struct heap* heap,
     53                              struct heap_node* newnode,
     54                              heap_compare_fn less_than));
     55 HEAP_EXPORT(void heap_remove(struct heap* heap,
     56                              struct heap_node* node,
     57                              heap_compare_fn less_than));
     58 HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than));
     59 
     60 /* Implementation follows. */
     61 
     62 HEAP_EXPORT(void heap_init(struct heap* heap)) {
     63   heap->min = NULL;
     64   heap->nelts = 0;
     65 }
     66 
     67 HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap)) {
     68   return heap->min;
     69 }
     70 
     71 /* Swap parent with child. Child moves closer to the root, parent moves away. */
     72 static void heap_node_swap(struct heap* heap,
     73                            struct heap_node* parent,
     74                            struct heap_node* child) {
     75   struct heap_node* sibling;
     76   struct heap_node t;
     77 
     78   t = *parent;
     79   *parent = *child;
     80   *child = t;
     81 
     82   parent->parent = child;
     83   if (child->left == child) {
     84     child->left = parent;
     85     sibling = child->right;
     86   } else {
     87     child->right = parent;
     88     sibling = child->left;
     89   }
     90   if (sibling != NULL)
     91     sibling->parent = child;
     92 
     93   if (parent->left != NULL)
     94     parent->left->parent = parent;
     95   if (parent->right != NULL)
     96     parent->right->parent = parent;
     97 
     98   if (child->parent == NULL)
     99     heap->min = child;
    100   else if (child->parent->left == parent)
    101     child->parent->left = child;
    102   else
    103     child->parent->right = child;
    104 }
    105 
    106 HEAP_EXPORT(void heap_insert(struct heap* heap,
    107                              struct heap_node* newnode,
    108                              heap_compare_fn less_than)) {
    109   struct heap_node** parent;
    110   struct heap_node** child;
    111   unsigned int path;
    112   unsigned int n;
    113   unsigned int k;
    114 
    115   newnode->left = NULL;
    116   newnode->right = NULL;
    117   newnode->parent = NULL;
    118 
    119   /* Calculate the path from the root to the insertion point.  This is a min
    120    * heap so we always insert at the left-most free node of the bottom row.
    121    */
    122   path = 0;
    123   for (k = 0, n = 1 + heap->nelts; n >= 2; k += 1, n /= 2)
    124     path = (path << 1) | (n & 1);
    125 
    126   /* Now traverse the heap using the path we calculated in the previous step. */
    127   parent = child = &heap->min;
    128   while (k > 0) {
    129     parent = child;
    130     if (path & 1)
    131       child = &(*child)->right;
    132     else
    133       child = &(*child)->left;
    134     path >>= 1;
    135     k -= 1;
    136   }
    137 
    138   /* Insert the new node. */
    139   newnode->parent = *parent;
    140   *child = newnode;
    141   heap->nelts += 1;
    142 
    143   /* Walk up the tree and check at each node if the heap property holds.
    144    * It's a min heap so parent < child must be true.
    145    */
    146   while (newnode->parent != NULL && less_than(newnode, newnode->parent))
    147     heap_node_swap(heap, newnode->parent, newnode);
    148 }
    149 
    150 HEAP_EXPORT(void heap_remove(struct heap* heap,
    151                              struct heap_node* node,
    152                              heap_compare_fn less_than)) {
    153   struct heap_node* smallest;
    154   struct heap_node** max;
    155   struct heap_node* child;
    156   unsigned int path;
    157   unsigned int k;
    158   unsigned int n;
    159 
    160   if (heap->nelts == 0)
    161     return;
    162 
    163   /* Calculate the path from the min (the root) to the max, the left-most node
    164    * of the bottom row.
    165    */
    166   path = 0;
    167   for (k = 0, n = heap->nelts; n >= 2; k += 1, n /= 2)
    168     path = (path << 1) | (n & 1);
    169 
    170   /* Now traverse the heap using the path we calculated in the previous step. */
    171   max = &heap->min;
    172   while (k > 0) {
    173     if (path & 1)
    174       max = &(*max)->right;
    175     else
    176       max = &(*max)->left;
    177     path >>= 1;
    178     k -= 1;
    179   }
    180 
    181   heap->nelts -= 1;
    182 
    183   /* Unlink the max node. */
    184   child = *max;
    185   *max = NULL;
    186 
    187   if (child == node) {
    188     /* We're removing either the max or the last node in the tree. */
    189     if (child == heap->min) {
    190       heap->min = NULL;
    191     }
    192     return;
    193   }
    194 
    195   /* Replace the to be deleted node with the max node. */
    196   child->left = node->left;
    197   child->right = node->right;
    198   child->parent = node->parent;
    199 
    200   if (child->left != NULL) {
    201     child->left->parent = child;
    202   }
    203 
    204   if (child->right != NULL) {
    205     child->right->parent = child;
    206   }
    207 
    208   if (node->parent == NULL) {
    209     heap->min = child;
    210   } else if (node->parent->left == node) {
    211     node->parent->left = child;
    212   } else {
    213     node->parent->right = child;
    214   }
    215 
    216   /* Walk down the subtree and check at each node if the heap property holds.
    217    * It's a min heap so parent < child must be true.  If the parent is bigger,
    218    * swap it with the smallest child.
    219    */
    220   for (;;) {
    221     smallest = child;
    222     if (child->left != NULL && less_than(child->left, smallest))
    223       smallest = child->left;
    224     if (child->right != NULL && less_than(child->right, smallest))
    225       smallest = child->right;
    226     if (smallest == child)
    227       break;
    228     heap_node_swap(heap, child, smallest);
    229   }
    230 
    231   /* Walk up the subtree and check that each parent is less than the node
    232    * this is required, because `max` node is not guaranteed to be the
    233    * actual maximum in tree
    234    */
    235   while (child->parent != NULL && less_than(child, child->parent))
    236     heap_node_swap(heap, child->parent, child);
    237 }
    238 
    239 HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than)) {
    240   heap_remove(heap, heap->min, less_than);
    241 }
    242 
    243 #undef HEAP_EXPORT
    244 
    245 #endif  /* UV_SRC_HEAP_H_ */
    246