Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmlibuv/src/heap-inl.h
3153 views
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_ */
246
247