Mercurial
comparison third_party/libuv/src/heap-inl.h @ 160:948de3f54cea
[ThirdParty] Added libuv
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Wed, 14 Jan 2026 19:39:52 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 159:05cf9467a1c3 | 160:948de3f54cea |
|---|---|
| 1 /* Copyright (c) 2013, Ben Noordhuis <[email protected]> | |
| 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_ */ |