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 | |
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 | |