PostgreSQL Source Code  git master
pairingheap.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * pairingheap.c
4  * A Pairing Heap implementation
5  *
6  * A pairing heap is a data structure that's useful for implementing
7  * priority queues. It is simple to implement, and provides amortized O(1)
8  * insert and find-min operations, and amortized O(log n) delete-min.
9  *
10  * The pairing heap was first described in this paper:
11  *
12  * Michael L. Fredman, Robert Sedgewick, Daniel D. Sleator, and Robert E.
13  * Tarjan. 1986.
14  * The pairing heap: a new form of self-adjusting heap.
15  * Algorithmica 1, 1 (January 1986), pages 111-129. DOI: 10.1007/BF01840439
16  *
17  * Portions Copyright (c) 2012-2024, PostgreSQL Global Development Group
18  *
19  * IDENTIFICATION
20  * src/backend/lib/pairingheap.c
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 #include "postgres.h"
26 
27 #include "lib/pairingheap.h"
28 
32  pairingheap_node *children);
33 
34 /*
35  * pairingheap_allocate
36  *
37  * Returns a pointer to a newly-allocated heap, with the heap property defined
38  * by the given comparator function, which will be invoked with the additional
39  * argument specified by 'arg'.
40  */
43 {
44  pairingheap *heap;
45 
46  heap = (pairingheap *) palloc(sizeof(pairingheap));
48 
49  return heap;
50 }
51 
52 /*
53  * pairingheap_initialize
54  *
55  * Same as pairingheap_allocate(), but initializes the pairing heap in-place
56  * rather than allocating a new chunk of memory. Useful to store the pairing
57  * heap in a shared memory.
58  */
59 void
61  void *arg)
62 {
63  heap->ph_compare = compare;
64  heap->ph_arg = arg;
65 
66  heap->ph_root = NULL;
67 }
68 
69 /*
70  * pairingheap_free
71  *
72  * Releases memory used by the given pairingheap.
73  *
74  * Note: The nodes in the heap are not freed!
75  */
76 void
78 {
79  pfree(heap);
80 }
81 
82 /*
83  * A helper function to merge two subheaps into one.
84  *
85  * The subheap with smaller value is put as a child of the other one (assuming
86  * a max-heap).
87  *
88  * The next_sibling and prev_or_parent pointers of the input nodes are
89  * ignored. On return, the returned node's next_sibling and prev_or_parent
90  * pointers are garbage.
91  */
92 static pairingheap_node *
94 {
95  if (a == NULL)
96  return b;
97  if (b == NULL)
98  return a;
99 
100  /* swap 'a' and 'b' so that 'a' is the one with larger value */
101  if (heap->ph_compare(a, b, heap->ph_arg) < 0)
102  {
103  pairingheap_node *tmp;
104 
105  tmp = a;
106  a = b;
107  b = tmp;
108  }
109 
110  /* and put 'b' as a child of 'a' */
111  if (a->first_child)
112  a->first_child->prev_or_parent = b;
113  b->prev_or_parent = a;
114  b->next_sibling = a->first_child;
115  a->first_child = b;
116 
117  return a;
118 }
119 
120 /*
121  * pairingheap_add
122  *
123  * Adds the given node to the heap in O(1) time.
124  */
125 void
127 {
128  node->first_child = NULL;
129 
130  /* Link the new node as a new tree */
131  heap->ph_root = merge(heap, heap->ph_root, node);
132  heap->ph_root->prev_or_parent = NULL;
133  heap->ph_root->next_sibling = NULL;
134 }
135 
136 /*
137  * pairingheap_first
138  *
139  * Returns a pointer to the first (root, topmost) node in the heap without
140  * modifying the heap. The caller must ensure that this routine is not used on
141  * an empty heap. Always O(1).
142  */
145 {
147 
148  return heap->ph_root;
149 }
150 
151 /*
152  * pairingheap_remove_first
153  *
154  * Removes the first (root, topmost) node in the heap and returns a pointer to
155  * it after rebalancing the heap. The caller must ensure that this routine is
156  * not used on an empty heap. O(log n) amortized.
157  */
160 {
161  pairingheap_node *result;
162  pairingheap_node *children;
163 
165 
166  /* Remove the root, and form a new heap of its children. */
167  result = heap->ph_root;
168  children = result->first_child;
169 
170  heap->ph_root = merge_children(heap, children);
171  if (heap->ph_root)
172  {
173  heap->ph_root->prev_or_parent = NULL;
174  heap->ph_root->next_sibling = NULL;
175  }
176 
177  return result;
178 }
179 
180 /*
181  * Remove 'node' from the heap. O(log n) amortized.
182  */
183 void
185 {
186  pairingheap_node *children;
187  pairingheap_node *replacement;
188  pairingheap_node *next_sibling;
189  pairingheap_node **prev_ptr;
190 
191  /*
192  * If the removed node happens to be the root node, do it with
193  * pairingheap_remove_first().
194  */
195  if (node == heap->ph_root)
196  {
197  (void) pairingheap_remove_first(heap);
198  return;
199  }
200 
201  /*
202  * Before we modify anything, remember the removed node's first_child and
203  * next_sibling pointers.
204  */
205  children = node->first_child;
206  next_sibling = node->next_sibling;
207 
208  /*
209  * Also find the pointer to the removed node in its previous sibling, or
210  * if this is the first child of its parent, in its parent.
211  */
212  if (node->prev_or_parent->first_child == node)
213  prev_ptr = &node->prev_or_parent->first_child;
214  else
215  prev_ptr = &node->prev_or_parent->next_sibling;
216  Assert(*prev_ptr == node);
217 
218  /*
219  * If this node has children, make a new subheap of the children and link
220  * the subheap in place of the removed node. Otherwise just unlink this
221  * node.
222  */
223  if (children)
224  {
225  replacement = merge_children(heap, children);
226 
227  replacement->prev_or_parent = node->prev_or_parent;
228  replacement->next_sibling = node->next_sibling;
229  *prev_ptr = replacement;
230  if (next_sibling)
231  next_sibling->prev_or_parent = replacement;
232  }
233  else
234  {
235  *prev_ptr = next_sibling;
236  if (next_sibling)
237  next_sibling->prev_or_parent = node->prev_or_parent;
238  }
239 }
240 
241 /*
242  * Merge a list of subheaps into a single heap.
243  *
244  * This implements the basic two-pass merging strategy, first forming pairs
245  * from left to right, and then merging the pairs.
246  */
247 static pairingheap_node *
249 {
250  pairingheap_node *curr,
251  *next;
252  pairingheap_node *pairs;
253  pairingheap_node *newroot;
254 
255  if (children == NULL || children->next_sibling == NULL)
256  return children;
257 
258  /* Walk the subheaps from left to right, merging in pairs */
259  next = children;
260  pairs = NULL;
261  for (;;)
262  {
263  curr = next;
264 
265  if (curr == NULL)
266  break;
267 
268  if (curr->next_sibling == NULL)
269  {
270  /* last odd node at the end of list */
271  curr->next_sibling = pairs;
272  pairs = curr;
273  break;
274  }
275 
276  next = curr->next_sibling->next_sibling;
277 
278  /* merge this and the next subheap, and add to 'pairs' list. */
279 
280  curr = merge(heap, curr, curr->next_sibling);
281  curr->next_sibling = pairs;
282  pairs = curr;
283  }
284 
285  /*
286  * Merge all the pairs together to form a single heap.
287  */
288  newroot = pairs;
289  next = pairs->next_sibling;
290  while (next)
291  {
292  curr = next;
293  next = curr->next_sibling;
294 
295  newroot = merge(heap, newroot, curr);
296  }
297 
298  return newroot;
299 }
300 
301 /*
302  * A debug function to dump the contents of the heap as a string.
303  *
304  * The 'dumpfunc' callback appends a string representation of a single node
305  * to the StringInfo. 'opaque' can be used to pass more information to the
306  * callback.
307  */
308 #ifdef PAIRINGHEAP_DEBUG
309 static void
310 pairingheap_dump_recurse(StringInfo buf,
311  pairingheap_node *node,
312  void (*dumpfunc) (pairingheap_node *node, StringInfo buf, void *opaque),
313  void *opaque,
314  int depth,
315  pairingheap_node *prev_or_parent)
316 {
317  while (node)
318  {
319  Assert(node->prev_or_parent == prev_or_parent);
320 
321  appendStringInfoSpaces(buf, depth * 4);
322  dumpfunc(node, buf, opaque);
323  appendStringInfoChar(buf, '\n');
324  if (node->first_child)
325  pairingheap_dump_recurse(buf, node->first_child, dumpfunc, opaque, depth + 1, node);
326  prev_or_parent = node;
327  node = node->next_sibling;
328  }
329 }
330 
331 char *
332 pairingheap_dump(pairingheap *heap,
333  void (*dumpfunc) (pairingheap_node *node, StringInfo buf, void *opaque),
334  void *opaque)
335 {
337 
338  if (!heap->ph_root)
339  return pstrdup("(empty)");
340 
342 
343  pairingheap_dump_recurse(&buf, heap->ph_root, dumpfunc, opaque, 0, NULL);
344 
345  return buf.data;
346 }
347 #endif
static int32 next
Definition: blutils.c:222
#define Assert(condition)
Definition: c.h:849
static int compare(const void *arg1, const void *arg2)
Definition: geqo_pool.c:145
int b
Definition: isn.c:70
int a
Definition: isn.c:69
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc(Size size)
Definition: mcxt.c:1317
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:184
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:126
static pairingheap_node * merge(pairingheap *heap, pairingheap_node *a, pairingheap_node *b)
Definition: pairingheap.c:93
pairingheap_node * pairingheap_first(pairingheap *heap)
Definition: pairingheap.c:144
pairingheap * pairingheap_allocate(pairingheap_comparator compare, void *arg)
Definition: pairingheap.c:42
void pairingheap_initialize(pairingheap *heap, pairingheap_comparator compare, void *arg)
Definition: pairingheap.c:60
void pairingheap_free(pairingheap *heap)
Definition: pairingheap.c:77
pairingheap_node * pairingheap_remove_first(pairingheap *heap)
Definition: pairingheap.c:159
static pairingheap_node * merge_children(pairingheap *heap, pairingheap_node *children)
Definition: pairingheap.c:248
#define pairingheap_is_empty(h)
Definition: pairingheap.h:99
int(* pairingheap_comparator)(const pairingheap_node *a, const pairingheap_node *b, void *arg)
Definition: pairingheap.h:60
void * arg
static char * buf
Definition: pg_test_fsync.c:73
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:212
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
struct pairingheap_node * next_sibling
Definition: pairingheap.h:33
struct pairingheap_node * prev_or_parent
Definition: pairingheap.h:34
struct pairingheap_node * first_child
Definition: pairingheap.h:32
pairingheap_comparator ph_compare
Definition: pairingheap.h:73
void * ph_arg
Definition: pairingheap.h:74
pairingheap_node * ph_root
Definition: pairingheap.h:75