1/* Copyright (c) 2013, Ben Noordhuis <info@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 27struct 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 */ 40struct heap { 41 struct heap_node* min; 42 unsigned int nelts; 43}; 44 45/* Return non-zero if a < b. */ 46typedef int (*heap_compare_fn)(const struct heap_node* a, 47 const struct heap_node* b); 48 49/* Public functions. */ 50HEAP_EXPORT(void heap_init(struct heap* heap)); 51HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap)); 52HEAP_EXPORT(void heap_insert(struct heap* heap, 53 struct heap_node* newnode, 54 heap_compare_fn less_than)); 55HEAP_EXPORT(void heap_remove(struct heap* heap, 56 struct heap_node* node, 57 heap_compare_fn less_than)); 58HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than)); 59 60/* Implementation follows. */ 61 62HEAP_EXPORT(void heap_init(struct heap* heap)) { 63 heap->min = NULL; 64 heap->nelts = 0; 65} 66 67HEAP_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. */ 72static 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 106HEAP_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 150HEAP_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 239HEAP_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