1 1.1 christos /* 2 1.1 christos * A Pairing Heap implementation. 3 1.1 christos * 4 1.1 christos * "The Pairing Heap: A New Form of Self-Adjusting Heap" 5 1.1 christos * https://www.cs.cmu.edu/~sleator/papers/pairing-heaps.pdf 6 1.1 christos * 7 1.1 christos * With auxiliary twopass list, described in a follow on paper. 8 1.1 christos * 9 1.1 christos * "Pairing Heaps: Experiments and Analysis" 10 1.1 christos * http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106.2988&rep=rep1&type=pdf 11 1.1 christos * 12 1.1 christos ******************************************************************************* 13 1.1 christos */ 14 1.1 christos 15 1.1 christos #ifndef PH_H_ 16 1.1 christos #define PH_H_ 17 1.1 christos 18 1.1 christos /* Node structure. */ 19 1.1 christos #define phn(a_type) \ 20 1.1 christos struct { \ 21 1.1 christos a_type *phn_prev; \ 22 1.1 christos a_type *phn_next; \ 23 1.1 christos a_type *phn_lchild; \ 24 1.1 christos } 25 1.1 christos 26 1.1 christos /* Root structure. */ 27 1.1 christos #define ph(a_type) \ 28 1.1 christos struct { \ 29 1.1 christos a_type *ph_root; \ 30 1.1 christos } 31 1.1 christos 32 1.1 christos /* Internal utility macros. */ 33 1.1 christos #define phn_lchild_get(a_type, a_field, a_phn) \ 34 1.1 christos (a_phn->a_field.phn_lchild) 35 1.1 christos #define phn_lchild_set(a_type, a_field, a_phn, a_lchild) do { \ 36 1.1 christos a_phn->a_field.phn_lchild = a_lchild; \ 37 1.1 christos } while (0) 38 1.1 christos 39 1.1 christos #define phn_next_get(a_type, a_field, a_phn) \ 40 1.1 christos (a_phn->a_field.phn_next) 41 1.1 christos #define phn_prev_set(a_type, a_field, a_phn, a_prev) do { \ 42 1.1 christos a_phn->a_field.phn_prev = a_prev; \ 43 1.1 christos } while (0) 44 1.1 christos 45 1.1 christos #define phn_prev_get(a_type, a_field, a_phn) \ 46 1.1 christos (a_phn->a_field.phn_prev) 47 1.1 christos #define phn_next_set(a_type, a_field, a_phn, a_next) do { \ 48 1.1 christos a_phn->a_field.phn_next = a_next; \ 49 1.1 christos } while (0) 50 1.1 christos 51 1.1 christos #define phn_merge_ordered(a_type, a_field, a_phn0, a_phn1, a_cmp) do { \ 52 1.1 christos a_type *phn0child; \ 53 1.1 christos \ 54 1.1 christos assert(a_phn0 != NULL); \ 55 1.1 christos assert(a_phn1 != NULL); \ 56 1.1 christos assert(a_cmp(a_phn0, a_phn1) <= 0); \ 57 1.1 christos \ 58 1.1 christos phn_prev_set(a_type, a_field, a_phn1, a_phn0); \ 59 1.1 christos phn0child = phn_lchild_get(a_type, a_field, a_phn0); \ 60 1.1 christos phn_next_set(a_type, a_field, a_phn1, phn0child); \ 61 1.1 christos if (phn0child != NULL) { \ 62 1.1 christos phn_prev_set(a_type, a_field, phn0child, a_phn1); \ 63 1.1 christos } \ 64 1.1 christos phn_lchild_set(a_type, a_field, a_phn0, a_phn1); \ 65 1.1 christos } while (0) 66 1.1 christos 67 1.1 christos #define phn_merge(a_type, a_field, a_phn0, a_phn1, a_cmp, r_phn) do { \ 68 1.1 christos if (a_phn0 == NULL) { \ 69 1.1 christos r_phn = a_phn1; \ 70 1.1 christos } else if (a_phn1 == NULL) { \ 71 1.1 christos r_phn = a_phn0; \ 72 1.1 christos } else if (a_cmp(a_phn0, a_phn1) < 0) { \ 73 1.1 christos phn_merge_ordered(a_type, a_field, a_phn0, a_phn1, \ 74 1.1 christos a_cmp); \ 75 1.1 christos r_phn = a_phn0; \ 76 1.1 christos } else { \ 77 1.1 christos phn_merge_ordered(a_type, a_field, a_phn1, a_phn0, \ 78 1.1 christos a_cmp); \ 79 1.1 christos r_phn = a_phn1; \ 80 1.1 christos } \ 81 1.1 christos } while (0) 82 1.1 christos 83 1.1 christos #define ph_merge_siblings(a_type, a_field, a_phn, a_cmp, r_phn) do { \ 84 1.1 christos a_type *head = NULL; \ 85 1.1 christos a_type *tail = NULL; \ 86 1.1 christos a_type *phn0 = a_phn; \ 87 1.1 christos a_type *phn1 = phn_next_get(a_type, a_field, phn0); \ 88 1.1 christos \ 89 1.1 christos /* \ 90 1.1 christos * Multipass merge, wherein the first two elements of a FIFO \ 91 1.1 christos * are repeatedly merged, and each result is appended to the \ 92 1.1 christos * singly linked FIFO, until the FIFO contains only a single \ 93 1.1 christos * element. We start with a sibling list but no reference to \ 94 1.1 christos * its tail, so we do a single pass over the sibling list to \ 95 1.1 christos * populate the FIFO. \ 96 1.1 christos */ \ 97 1.1 christos if (phn1 != NULL) { \ 98 1.1 christos a_type *phnrest = phn_next_get(a_type, a_field, phn1); \ 99 1.1 christos if (phnrest != NULL) { \ 100 1.1 christos phn_prev_set(a_type, a_field, phnrest, NULL); \ 101 1.1 christos } \ 102 1.1 christos phn_prev_set(a_type, a_field, phn0, NULL); \ 103 1.1 christos phn_next_set(a_type, a_field, phn0, NULL); \ 104 1.1 christos phn_prev_set(a_type, a_field, phn1, NULL); \ 105 1.1 christos phn_next_set(a_type, a_field, phn1, NULL); \ 106 1.1 christos phn_merge(a_type, a_field, phn0, phn1, a_cmp, phn0); \ 107 1.1 christos head = tail = phn0; \ 108 1.1 christos phn0 = phnrest; \ 109 1.1 christos while (phn0 != NULL) { \ 110 1.1 christos phn1 = phn_next_get(a_type, a_field, phn0); \ 111 1.1 christos if (phn1 != NULL) { \ 112 1.1 christos phnrest = phn_next_get(a_type, a_field, \ 113 1.1 christos phn1); \ 114 1.1 christos if (phnrest != NULL) { \ 115 1.1 christos phn_prev_set(a_type, a_field, \ 116 1.1 christos phnrest, NULL); \ 117 1.1 christos } \ 118 1.1 christos phn_prev_set(a_type, a_field, phn0, \ 119 1.1 christos NULL); \ 120 1.1 christos phn_next_set(a_type, a_field, phn0, \ 121 1.1 christos NULL); \ 122 1.1 christos phn_prev_set(a_type, a_field, phn1, \ 123 1.1 christos NULL); \ 124 1.1 christos phn_next_set(a_type, a_field, phn1, \ 125 1.1 christos NULL); \ 126 1.1 christos phn_merge(a_type, a_field, phn0, phn1, \ 127 1.1 christos a_cmp, phn0); \ 128 1.1 christos phn_next_set(a_type, a_field, tail, \ 129 1.1 christos phn0); \ 130 1.1 christos tail = phn0; \ 131 1.1 christos phn0 = phnrest; \ 132 1.1 christos } else { \ 133 1.1 christos phn_next_set(a_type, a_field, tail, \ 134 1.1 christos phn0); \ 135 1.1 christos tail = phn0; \ 136 1.1 christos phn0 = NULL; \ 137 1.1 christos } \ 138 1.1 christos } \ 139 1.1 christos phn0 = head; \ 140 1.1 christos phn1 = phn_next_get(a_type, a_field, phn0); \ 141 1.1 christos if (phn1 != NULL) { \ 142 1.1 christos while (true) { \ 143 1.1 christos head = phn_next_get(a_type, a_field, \ 144 1.1 christos phn1); \ 145 1.1 christos assert(phn_prev_get(a_type, a_field, \ 146 1.1 christos phn0) == NULL); \ 147 1.1 christos phn_next_set(a_type, a_field, phn0, \ 148 1.1 christos NULL); \ 149 1.1 christos assert(phn_prev_get(a_type, a_field, \ 150 1.1 christos phn1) == NULL); \ 151 1.1 christos phn_next_set(a_type, a_field, phn1, \ 152 1.1 christos NULL); \ 153 1.1 christos phn_merge(a_type, a_field, phn0, phn1, \ 154 1.1 christos a_cmp, phn0); \ 155 1.1 christos if (head == NULL) { \ 156 1.1 christos break; \ 157 1.1 christos } \ 158 1.1 christos phn_next_set(a_type, a_field, tail, \ 159 1.1 christos phn0); \ 160 1.1 christos tail = phn0; \ 161 1.1 christos phn0 = head; \ 162 1.1 christos phn1 = phn_next_get(a_type, a_field, \ 163 1.1 christos phn0); \ 164 1.1 christos } \ 165 1.1 christos } \ 166 1.1 christos } \ 167 1.1 christos r_phn = phn0; \ 168 1.1 christos } while (0) 169 1.1 christos 170 1.1 christos #define ph_merge_aux(a_type, a_field, a_ph, a_cmp) do { \ 171 1.1 christos a_type *_phn = phn_next_get(a_type, a_field, a_ph->ph_root); \ 172 1.1 christos if (_phn != NULL) { \ 173 1.1 christos phn_prev_set(a_type, a_field, a_ph->ph_root, NULL); \ 174 1.1 christos phn_next_set(a_type, a_field, a_ph->ph_root, NULL); \ 175 1.1 christos phn_prev_set(a_type, a_field, _phn, NULL); \ 176 1.1 christos ph_merge_siblings(a_type, a_field, _phn, a_cmp, _phn); \ 177 1.1 christos assert(phn_next_get(a_type, a_field, _phn) == NULL); \ 178 1.1 christos phn_merge(a_type, a_field, a_ph->ph_root, _phn, a_cmp, \ 179 1.1 christos a_ph->ph_root); \ 180 1.1 christos } \ 181 1.1 christos } while (0) 182 1.1 christos 183 1.1 christos #define ph_merge_children(a_type, a_field, a_phn, a_cmp, r_phn) do { \ 184 1.1 christos a_type *lchild = phn_lchild_get(a_type, a_field, a_phn); \ 185 1.1 christos if (lchild == NULL) { \ 186 1.1 christos r_phn = NULL; \ 187 1.1 christos } else { \ 188 1.1 christos ph_merge_siblings(a_type, a_field, lchild, a_cmp, \ 189 1.1 christos r_phn); \ 190 1.1 christos } \ 191 1.1 christos } while (0) 192 1.1 christos 193 1.1 christos /* 194 1.1 christos * The ph_proto() macro generates function prototypes that correspond to the 195 1.1 christos * functions generated by an equivalently parameterized call to ph_gen(). 196 1.1 christos */ 197 1.1 christos #define ph_proto(a_attr, a_prefix, a_ph_type, a_type) \ 198 1.1 christos a_attr void a_prefix##new(a_ph_type *ph); \ 199 1.1 christos a_attr bool a_prefix##empty(a_ph_type *ph); \ 200 1.1 christos a_attr a_type *a_prefix##first(a_ph_type *ph); \ 201 1.1 christos a_attr a_type *a_prefix##any(a_ph_type *ph); \ 202 1.1 christos a_attr void a_prefix##insert(a_ph_type *ph, a_type *phn); \ 203 1.1 christos a_attr a_type *a_prefix##remove_first(a_ph_type *ph); \ 204 1.1 christos a_attr a_type *a_prefix##remove_any(a_ph_type *ph); \ 205 1.1 christos a_attr void a_prefix##remove(a_ph_type *ph, a_type *phn); 206 1.1 christos 207 1.1 christos /* 208 1.1 christos * The ph_gen() macro generates a type-specific pairing heap implementation, 209 1.1 christos * based on the above cpp macros. 210 1.1 christos */ 211 1.1 christos #define ph_gen(a_attr, a_prefix, a_ph_type, a_type, a_field, a_cmp) \ 212 1.1 christos a_attr void \ 213 1.1 christos a_prefix##new(a_ph_type *ph) { \ 214 1.1 christos memset(ph, 0, sizeof(ph(a_type))); \ 215 1.1 christos } \ 216 1.1 christos a_attr bool \ 217 1.1 christos a_prefix##empty(a_ph_type *ph) { \ 218 1.1 christos return (ph->ph_root == NULL); \ 219 1.1 christos } \ 220 1.1 christos a_attr a_type * \ 221 1.1 christos a_prefix##first(a_ph_type *ph) { \ 222 1.1 christos if (ph->ph_root == NULL) { \ 223 1.1 christos return NULL; \ 224 1.1 christos } \ 225 1.1 christos ph_merge_aux(a_type, a_field, ph, a_cmp); \ 226 1.1 christos return ph->ph_root; \ 227 1.1 christos } \ 228 1.1 christos a_attr a_type * \ 229 1.1 christos a_prefix##any(a_ph_type *ph) { \ 230 1.1 christos if (ph->ph_root == NULL) { \ 231 1.1 christos return NULL; \ 232 1.1 christos } \ 233 1.1 christos a_type *aux = phn_next_get(a_type, a_field, ph->ph_root); \ 234 1.1 christos if (aux != NULL) { \ 235 1.1 christos return aux; \ 236 1.1 christos } \ 237 1.1 christos return ph->ph_root; \ 238 1.1 christos } \ 239 1.1 christos a_attr void \ 240 1.1 christos a_prefix##insert(a_ph_type *ph, a_type *phn) { \ 241 1.1 christos memset(&phn->a_field, 0, sizeof(phn(a_type))); \ 242 1.1 christos \ 243 1.1 christos /* \ 244 1.1 christos * Treat the root as an aux list during insertion, and lazily \ 245 1.1 christos * merge during a_prefix##remove_first(). For elements that \ 246 1.1 christos * are inserted, then removed via a_prefix##remove() before the \ 247 1.1 christos * aux list is ever processed, this makes insert/remove \ 248 1.1 christos * constant-time, whereas eager merging would make insert \ 249 1.1 christos * O(log n). \ 250 1.1 christos */ \ 251 1.1 christos if (ph->ph_root == NULL) { \ 252 1.1 christos ph->ph_root = phn; \ 253 1.1 christos } else { \ 254 1.1 christos phn_next_set(a_type, a_field, phn, phn_next_get(a_type, \ 255 1.1 christos a_field, ph->ph_root)); \ 256 1.1 christos if (phn_next_get(a_type, a_field, ph->ph_root) != \ 257 1.1 christos NULL) { \ 258 1.1 christos phn_prev_set(a_type, a_field, \ 259 1.1 christos phn_next_get(a_type, a_field, ph->ph_root), \ 260 1.1 christos phn); \ 261 1.1 christos } \ 262 1.1 christos phn_prev_set(a_type, a_field, phn, ph->ph_root); \ 263 1.1 christos phn_next_set(a_type, a_field, ph->ph_root, phn); \ 264 1.1 christos } \ 265 1.1 christos } \ 266 1.1 christos a_attr a_type * \ 267 1.1 christos a_prefix##remove_first(a_ph_type *ph) { \ 268 1.1 christos a_type *ret; \ 269 1.1 christos \ 270 1.1 christos if (ph->ph_root == NULL) { \ 271 1.1 christos return NULL; \ 272 1.1 christos } \ 273 1.1 christos ph_merge_aux(a_type, a_field, ph, a_cmp); \ 274 1.1 christos \ 275 1.1 christos ret = ph->ph_root; \ 276 1.1 christos \ 277 1.1 christos ph_merge_children(a_type, a_field, ph->ph_root, a_cmp, \ 278 1.1 christos ph->ph_root); \ 279 1.1 christos \ 280 1.1 christos return ret; \ 281 1.1 christos } \ 282 1.1 christos a_attr a_type * \ 283 1.1 christos a_prefix##remove_any(a_ph_type *ph) { \ 284 1.1 christos /* \ 285 1.1 christos * Remove the most recently inserted aux list element, or the \ 286 1.1 christos * root if the aux list is empty. This has the effect of \ 287 1.1 christos * behaving as a LIFO (and insertion/removal is therefore \ 288 1.1 christos * constant-time) if a_prefix##[remove_]first() are never \ 289 1.1 christos * called. \ 290 1.1 christos */ \ 291 1.1 christos if (ph->ph_root == NULL) { \ 292 1.1 christos return NULL; \ 293 1.1 christos } \ 294 1.1 christos a_type *ret = phn_next_get(a_type, a_field, ph->ph_root); \ 295 1.1 christos if (ret != NULL) { \ 296 1.1 christos a_type *aux = phn_next_get(a_type, a_field, ret); \ 297 1.1 christos phn_next_set(a_type, a_field, ph->ph_root, aux); \ 298 1.1 christos if (aux != NULL) { \ 299 1.1 christos phn_prev_set(a_type, a_field, aux, \ 300 1.1 christos ph->ph_root); \ 301 1.1 christos } \ 302 1.1 christos return ret; \ 303 1.1 christos } \ 304 1.1 christos ret = ph->ph_root; \ 305 1.1 christos ph_merge_children(a_type, a_field, ph->ph_root, a_cmp, \ 306 1.1 christos ph->ph_root); \ 307 1.1 christos return ret; \ 308 1.1 christos } \ 309 1.1 christos a_attr void \ 310 1.1 christos a_prefix##remove(a_ph_type *ph, a_type *phn) { \ 311 1.1 christos a_type *replace, *parent; \ 312 1.1 christos \ 313 1.1 christos if (ph->ph_root == phn) { \ 314 1.1 christos /* \ 315 1.1 christos * We can delete from aux list without merging it, but \ 316 1.1 christos * we need to merge if we are dealing with the root \ 317 1.1 christos * node and it has children. \ 318 1.1 christos */ \ 319 1.1 christos if (phn_lchild_get(a_type, a_field, phn) == NULL) { \ 320 1.1 christos ph->ph_root = phn_next_get(a_type, a_field, \ 321 1.1 christos phn); \ 322 1.1 christos if (ph->ph_root != NULL) { \ 323 1.1 christos phn_prev_set(a_type, a_field, \ 324 1.1 christos ph->ph_root, NULL); \ 325 1.1 christos } \ 326 1.1 christos return; \ 327 1.1 christos } \ 328 1.1 christos ph_merge_aux(a_type, a_field, ph, a_cmp); \ 329 1.1 christos if (ph->ph_root == phn) { \ 330 1.1 christos ph_merge_children(a_type, a_field, ph->ph_root, \ 331 1.1 christos a_cmp, ph->ph_root); \ 332 1.1 christos return; \ 333 1.1 christos } \ 334 1.1 christos } \ 335 1.1 christos \ 336 1.1 christos /* Get parent (if phn is leftmost child) before mutating. */ \ 337 1.1 christos if ((parent = phn_prev_get(a_type, a_field, phn)) != NULL) { \ 338 1.1 christos if (phn_lchild_get(a_type, a_field, parent) != phn) { \ 339 1.1 christos parent = NULL; \ 340 1.1 christos } \ 341 1.1 christos } \ 342 1.1 christos /* Find a possible replacement node, and link to parent. */ \ 343 1.1 christos ph_merge_children(a_type, a_field, phn, a_cmp, replace); \ 344 1.1 christos /* Set next/prev for sibling linked list. */ \ 345 1.1 christos if (replace != NULL) { \ 346 1.1 christos if (parent != NULL) { \ 347 1.1 christos phn_prev_set(a_type, a_field, replace, parent); \ 348 1.1 christos phn_lchild_set(a_type, a_field, parent, \ 349 1.1 christos replace); \ 350 1.1 christos } else { \ 351 1.1 christos phn_prev_set(a_type, a_field, replace, \ 352 1.1 christos phn_prev_get(a_type, a_field, phn)); \ 353 1.1 christos if (phn_prev_get(a_type, a_field, phn) != \ 354 1.1 christos NULL) { \ 355 1.1 christos phn_next_set(a_type, a_field, \ 356 1.1 christos phn_prev_get(a_type, a_field, phn), \ 357 1.1 christos replace); \ 358 1.1 christos } \ 359 1.1 christos } \ 360 1.1 christos phn_next_set(a_type, a_field, replace, \ 361 1.1 christos phn_next_get(a_type, a_field, phn)); \ 362 1.1 christos if (phn_next_get(a_type, a_field, phn) != NULL) { \ 363 1.1 christos phn_prev_set(a_type, a_field, \ 364 1.1 christos phn_next_get(a_type, a_field, phn), \ 365 1.1 christos replace); \ 366 1.1 christos } \ 367 1.1 christos } else { \ 368 1.1 christos if (parent != NULL) { \ 369 1.1 christos a_type *next = phn_next_get(a_type, a_field, \ 370 1.1 christos phn); \ 371 1.1 christos phn_lchild_set(a_type, a_field, parent, next); \ 372 1.1 christos if (next != NULL) { \ 373 1.1 christos phn_prev_set(a_type, a_field, next, \ 374 1.1 christos parent); \ 375 1.1 christos } \ 376 1.1 christos } else { \ 377 1.1 christos assert(phn_prev_get(a_type, a_field, phn) != \ 378 1.1 christos NULL); \ 379 1.1 christos phn_next_set(a_type, a_field, \ 380 1.1 christos phn_prev_get(a_type, a_field, phn), \ 381 1.1 christos phn_next_get(a_type, a_field, phn)); \ 382 1.1 christos } \ 383 1.1 christos if (phn_next_get(a_type, a_field, phn) != NULL) { \ 384 1.1 christos phn_prev_set(a_type, a_field, \ 385 1.1 christos phn_next_get(a_type, a_field, phn), \ 386 1.1 christos phn_prev_get(a_type, a_field, phn)); \ 387 1.1 christos } \ 388 1.1 christos } \ 389 1.1 christos } 390 1.1 christos 391 1.1 christos #endif /* PH_H_ */ 392