2 * A Pairing Heap implementation.
4 * "The Pairing Heap: A New Form of Self-Adjusting Heap"
5 * https://www.cs.cmu.edu/~sleator/papers/pairing-heaps.pdf
7 * With auxiliary twopass list, described in a follow on paper.
9 * "Pairing Heaps: Experiments and Analysis"
10 * http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106.2988&rep=rep1&type=pdf
12 *******************************************************************************
32 /* Internal utility macros. */
33 #define phn_lchild_get(a_type, a_field, a_phn) \
34 (a_phn->a_field.phn_lchild)
35 #define phn_lchild_set(a_type, a_field, a_phn, a_lchild) do { \
36 a_phn->a_field.phn_lchild = a_lchild; \
39 #define phn_next_get(a_type, a_field, a_phn) \
40 (a_phn->a_field.phn_next)
41 #define phn_prev_set(a_type, a_field, a_phn, a_prev) do { \
42 a_phn->a_field.phn_prev = a_prev; \
45 #define phn_prev_get(a_type, a_field, a_phn) \
46 (a_phn->a_field.phn_prev)
47 #define phn_next_set(a_type, a_field, a_phn, a_next) do { \
48 a_phn->a_field.phn_next = a_next; \
51 #define phn_merge_ordered(a_type, a_field, a_phn0, a_phn1, a_cmp) do { \
54 assert(a_phn0 != NULL); \
55 assert(a_phn1 != NULL); \
56 assert(a_cmp(a_phn0, a_phn1) <= 0); \
58 phn_prev_set(a_type, a_field, a_phn1, a_phn0); \
59 phn0child = phn_lchild_get(a_type, a_field, a_phn0); \
60 phn_next_set(a_type, a_field, a_phn1, phn0child); \
61 if (phn0child != NULL) { \
62 phn_prev_set(a_type, a_field, phn0child, a_phn1); \
64 phn_lchild_set(a_type, a_field, a_phn0, a_phn1); \
67 #define phn_merge(a_type, a_field, a_phn0, a_phn1, a_cmp, r_phn) do { \
68 if (a_phn0 == NULL) { \
70 } else if (a_phn1 == NULL) { \
72 } else if (a_cmp(a_phn0, a_phn1) < 0) { \
73 phn_merge_ordered(a_type, a_field, a_phn0, a_phn1, \
77 phn_merge_ordered(a_type, a_field, a_phn1, a_phn0, \
83 #define ph_merge_siblings(a_type, a_field, a_phn, a_cmp, r_phn) do { \
84 a_type *head = NULL; \
85 a_type *tail = NULL; \
86 a_type *phn0 = a_phn; \
87 a_type *phn1 = phn_next_get(a_type, a_field, phn0); \
90 * Multipass merge, wherein the first two elements of a FIFO \
91 * are repeatedly merged, and each result is appended to the \
92 * singly linked FIFO, until the FIFO contains only a single \
93 * element. We start with a sibling list but no reference to \
94 * its tail, so we do a single pass over the sibling list to \
95 * populate the FIFO. \
98 a_type *phnrest = phn_next_get(a_type, a_field, phn1); \
99 if (phnrest != NULL) { \
100 phn_prev_set(a_type, a_field, phnrest, NULL); \
102 phn_prev_set(a_type, a_field, phn0, NULL); \
103 phn_next_set(a_type, a_field, phn0, NULL); \
104 phn_prev_set(a_type, a_field, phn1, NULL); \
105 phn_next_set(a_type, a_field, phn1, NULL); \
106 phn_merge(a_type, a_field, phn0, phn1, a_cmp, phn0); \
107 head = tail = phn0; \
109 while (phn0 != NULL) { \
110 phn1 = phn_next_get(a_type, a_field, phn0); \
111 if (phn1 != NULL) { \
112 phnrest = phn_next_get(a_type, a_field, \
114 if (phnrest != NULL) { \
115 phn_prev_set(a_type, a_field, \
118 phn_prev_set(a_type, a_field, phn0, \
120 phn_next_set(a_type, a_field, phn0, \
122 phn_prev_set(a_type, a_field, phn1, \
124 phn_next_set(a_type, a_field, phn1, \
126 phn_merge(a_type, a_field, phn0, phn1, \
128 phn_next_set(a_type, a_field, tail, \
133 phn_next_set(a_type, a_field, tail, \
140 phn1 = phn_next_get(a_type, a_field, phn0); \
141 if (phn1 != NULL) { \
143 head = phn_next_get(a_type, a_field, \
145 assert(phn_prev_get(a_type, a_field, \
147 phn_next_set(a_type, a_field, phn0, \
149 assert(phn_prev_get(a_type, a_field, \
151 phn_next_set(a_type, a_field, phn1, \
153 phn_merge(a_type, a_field, phn0, phn1, \
155 if (head == NULL) { \
158 phn_next_set(a_type, a_field, tail, \
162 phn1 = phn_next_get(a_type, a_field, \
170 #define ph_merge_aux(a_type, a_field, a_ph, a_cmp) do { \
171 a_type *phn = phn_next_get(a_type, a_field, a_ph->ph_root); \
173 phn_prev_set(a_type, a_field, a_ph->ph_root, NULL); \
174 phn_next_set(a_type, a_field, a_ph->ph_root, NULL); \
175 phn_prev_set(a_type, a_field, phn, NULL); \
176 ph_merge_siblings(a_type, a_field, phn, a_cmp, phn); \
177 assert(phn_next_get(a_type, a_field, phn) == NULL); \
178 phn_merge(a_type, a_field, a_ph->ph_root, phn, a_cmp, \
183 #define ph_merge_children(a_type, a_field, a_phn, a_cmp, r_phn) do { \
184 a_type *lchild = phn_lchild_get(a_type, a_field, a_phn); \
185 if (lchild == NULL) { \
188 ph_merge_siblings(a_type, a_field, lchild, a_cmp, \
194 * The ph_proto() macro generates function prototypes that correspond to the
195 * functions generated by an equivalently parameterized call to ph_gen().
197 #define ph_proto(a_attr, a_prefix, a_ph_type, a_type) \
198 a_attr void a_prefix##new(a_ph_type *ph); \
199 a_attr bool a_prefix##empty(a_ph_type *ph); \
200 a_attr a_type *a_prefix##first(a_ph_type *ph); \
201 a_attr a_type *a_prefix##any(a_ph_type *ph); \
202 a_attr void a_prefix##insert(a_ph_type *ph, a_type *phn); \
203 a_attr a_type *a_prefix##remove_first(a_ph_type *ph); \
204 a_attr a_type *a_prefix##remove_any(a_ph_type *ph); \
205 a_attr void a_prefix##remove(a_ph_type *ph, a_type *phn);
208 * The ph_gen() macro generates a type-specific pairing heap implementation,
209 * based on the above cpp macros.
211 #define ph_gen(a_attr, a_prefix, a_ph_type, a_type, a_field, a_cmp) \
213 a_prefix##new(a_ph_type *ph) { \
214 memset(ph, 0, sizeof(ph(a_type))); \
217 a_prefix##empty(a_ph_type *ph) { \
218 return (ph->ph_root == NULL); \
221 a_prefix##first(a_ph_type *ph) { \
222 if (ph->ph_root == NULL) { \
225 ph_merge_aux(a_type, a_field, ph, a_cmp); \
226 return ph->ph_root; \
229 a_prefix##any(a_ph_type *ph) { \
230 if (ph->ph_root == NULL) { \
233 a_type *aux = phn_next_get(a_type, a_field, ph->ph_root); \
237 return ph->ph_root; \
240 a_prefix##insert(a_ph_type *ph, a_type *phn) { \
241 memset(&phn->a_field, 0, sizeof(phn(a_type))); \
244 * Treat the root as an aux list during insertion, and lazily \
245 * merge during a_prefix##remove_first(). For elements that \
246 * are inserted, then removed via a_prefix##remove() before the \
247 * aux list is ever processed, this makes insert/remove \
248 * constant-time, whereas eager merging would make insert \
251 if (ph->ph_root == NULL) { \
254 phn_next_set(a_type, a_field, phn, phn_next_get(a_type, \
255 a_field, ph->ph_root)); \
256 if (phn_next_get(a_type, a_field, ph->ph_root) != \
258 phn_prev_set(a_type, a_field, \
259 phn_next_get(a_type, a_field, ph->ph_root), \
262 phn_prev_set(a_type, a_field, phn, ph->ph_root); \
263 phn_next_set(a_type, a_field, ph->ph_root, phn); \
267 a_prefix##remove_first(a_ph_type *ph) { \
270 if (ph->ph_root == NULL) { \
273 ph_merge_aux(a_type, a_field, ph, a_cmp); \
277 ph_merge_children(a_type, a_field, ph->ph_root, a_cmp, \
283 a_prefix##remove_any(a_ph_type *ph) { \
285 * Remove the most recently inserted aux list element, or the \
286 * root if the aux list is empty. This has the effect of \
287 * behaving as a LIFO (and insertion/removal is therefore \
288 * constant-time) if a_prefix##[remove_]first() are never \
291 if (ph->ph_root == NULL) { \
294 a_type *ret = phn_next_get(a_type, a_field, ph->ph_root); \
296 a_type *aux = phn_next_get(a_type, a_field, ret); \
297 phn_next_set(a_type, a_field, ph->ph_root, aux); \
299 phn_prev_set(a_type, a_field, aux, \
305 ph_merge_children(a_type, a_field, ph->ph_root, a_cmp, \
310 a_prefix##remove(a_ph_type *ph, a_type *phn) { \
311 a_type *replace, *parent; \
313 if (ph->ph_root == phn) { \
315 * We can delete from aux list without merging it, but \
316 * we need to merge if we are dealing with the root \
317 * node and it has children. \
319 if (phn_lchild_get(a_type, a_field, phn) == NULL) { \
320 ph->ph_root = phn_next_get(a_type, a_field, \
322 if (ph->ph_root != NULL) { \
323 phn_prev_set(a_type, a_field, \
324 ph->ph_root, NULL); \
328 ph_merge_aux(a_type, a_field, ph, a_cmp); \
329 if (ph->ph_root == phn) { \
330 ph_merge_children(a_type, a_field, ph->ph_root, \
331 a_cmp, ph->ph_root); \
336 /* Get parent (if phn is leftmost child) before mutating. */ \
337 if ((parent = phn_prev_get(a_type, a_field, phn)) != NULL) { \
338 if (phn_lchild_get(a_type, a_field, parent) != phn) { \
342 /* Find a possible replacement node, and link to parent. */ \
343 ph_merge_children(a_type, a_field, phn, a_cmp, replace); \
344 /* Set next/prev for sibling linked list. */ \
345 if (replace != NULL) { \
346 if (parent != NULL) { \
347 phn_prev_set(a_type, a_field, replace, parent); \
348 phn_lchild_set(a_type, a_field, parent, \
351 phn_prev_set(a_type, a_field, replace, \
352 phn_prev_get(a_type, a_field, phn)); \
353 if (phn_prev_get(a_type, a_field, phn) != \
355 phn_next_set(a_type, a_field, \
356 phn_prev_get(a_type, a_field, phn), \
360 phn_next_set(a_type, a_field, replace, \
361 phn_next_get(a_type, a_field, phn)); \
362 if (phn_next_get(a_type, a_field, phn) != NULL) { \
363 phn_prev_set(a_type, a_field, \
364 phn_next_get(a_type, a_field, phn), \
368 if (parent != NULL) { \
369 a_type *next = phn_next_get(a_type, a_field, \
371 phn_lchild_set(a_type, a_field, parent, next); \
372 if (next != NULL) { \
373 phn_prev_set(a_type, a_field, next, \
377 assert(phn_prev_get(a_type, a_field, phn) != \
379 phn_next_set(a_type, a_field, \
380 phn_prev_get(a_type, a_field, phn), \
381 phn_next_get(a_type, a_field, phn)); \
383 if (phn_next_get(a_type, a_field, phn) != NULL) { \
384 phn_prev_set(a_type, a_field, \
385 phn_next_get(a_type, a_field, phn), \
386 phn_prev_get(a_type, a_field, phn)); \