2 * UCW Library -- Binomial Heaps
4 * (c) 2003 Martin Mares <mj@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
11 * This is a generic implementation of Binomial Heaps. Each time you include
12 * this file with parameters set in the corresponding preprocessor macros
13 * as described below, it generates functions for manipulating the particular
14 * version of the binomial heap.
19 * Interface to the generator
20 * --------------------------
22 * To use the binomial heaps, you need to specify:
24 * - `BH_PREFIX(x)` -- macro to add a name prefix (used on all global names
25 * defined by the generator). All further names mentioned
26 * here except for macro names will be implicitly prefixed.
28 * Then you continue by including `ucw/binheap-node.h` which defines <<struct_bh_node,struct bh_node>>
29 * and <<struct_bh_heap,struct bh_heap>> (both without prefix). The heap elements are always allocated by
30 * you and they must include `struct bh_node` which serves as a handle used for all
31 * the heap functions and it contains all information needed for heap-keeping.
32 * The heap itself is also allocated by you and it's represented by `struct bh_heap`.
34 * When you have the declaration of heap nodes, you continue with defining:
36 * - `less(p,q)` -- returns `1` if the key corresponding to `bh_node *p`
37 * is less than the one corresponding to `*q`.
39 * Then specify what operations you request:
41 * - `init(heap\*)` -- initialize the heap (always defined).
42 * - `insert(heap\*, node\*)` -- insert the node to the heap (`BH_WANT_INSERT`).
43 * - `node\* findmin(heap\*)` -- find node with minimum key (`BH_WANT_FINDMIN`).
44 * - `node\* deletemin(heap\*)` -- findmin and delete the node (`BH_WANT_DELETEMIN`).
46 * Then include `ucw/binheap.h` and voila, you have a binomial heap
47 * suiting all your needs (at least those which you've revealed :) ).
49 * You also get a iterator macro at no extra charge:
51 * BH_FOR_ALL(bh_prefix, heap*, variable)
53 * // node* variable gets declared automatically
54 * do_something_with_node(variable);
55 * // use BH_BREAK and BH_CONTINUE instead of break and continue
56 * // you must not alter contents of the binomial heap here
60 * After including this file, all parameter macros are automatically undef'd.
63 #define BH_NODE struct bh_node
64 #define BH_HEAP struct bh_heap
67 BH_PREFIX(merge)(BH_NODE *a, BH_NODE *b)
69 BH_NODE **pp = &a->first_son;
70 BH_NODE *q = b->first_son;
73 while ((p = *pp) && q)
75 /* p,q are the next nodes of a,b; pp points to where p is linked */
76 if (p->order < q->order) /* p is smaller => skip it */
77 pp = &p->next_sibling;
78 else if (p->order > q->order) /* q is smaller => insert it before p */
84 pp = &r->next_sibling;
86 else /* p and q are of the same order => need to merge them */
88 if (BH_PREFIX(less)(p, q)) /* we'll hang r below s */
98 *pp = p->next_sibling; /* unlink p,q from their lists */
101 if (s->last_son) /* merge r to s, increasing order */
102 s->last_son->next_sibling = r;
107 r->next_sibling = NULL;
109 if (!q || q->order > s->order) /* put the result into the b's list if possible */
114 else /* otherwise put the result to the a's list */
116 p = s->next_sibling = *pp;
118 if (p && p->order == s->order) /* 3-collision */
119 pp = &s->next_sibling;
127 #ifdef BH_WANT_INSERT
129 BH_PREFIX(insert)(BH_HEAP *heap, BH_NODE *a)
134 a->first_son = a->last_son = a->next_sibling = NULL;
136 BH_PREFIX(merge)(&heap->root, &sh);
140 #ifdef BH_WANT_FINDMIN
142 BH_PREFIX(findmin)(BH_HEAP *heap)
147 for (p=heap->root.first_son; p; p=p->next_sibling)
148 if (!best || BH_PREFIX(less)(p, best))
154 #ifdef BH_WANT_DELETEMIN
156 BH_PREFIX(deletemin)(BH_HEAP *heap)
158 BH_NODE *p, **pp, **bestp;
161 for (pp=&heap->root.first_son; p=*pp; pp=&p->next_sibling)
162 if (!bestp || BH_PREFIX(less)(p, *bestp))
168 *bestp = p->next_sibling;
169 BH_PREFIX(merge)(&heap->root, p);
175 BH_PREFIX(init)(BH_HEAP *heap)
177 bzero(heap, sizeof(*heap));
182 #define BH_FOR_ALL(bh_px, bh_heap, bh_var) \
184 struct bh_node *bh_stack[32]; \
186 if (bh_stack[0] = (bh_heap)->root.first_son) \
189 struct bh_node *bh_var = bh_stack[--bh_sp]; \
190 if (bh_var->next_sibling) \
191 bh_stack[bh_sp++] = bh_var->next_sibling; \
192 if (bh_var->first_son) \
193 bh_stack[bh_sp++] = bh_var->first_son;
198 #define BH_BREAK { bh_sp=0; break; }
199 #define BH_CONTINUE continue
206 #undef BH_WANT_INSERT
207 #undef BH_WANT_FINDMIN
208 #undef BH_WANT_DELETEMIN