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.
16 * You need to specify:
18 * BH_PREFIX(x) macro to add a name prefix (used on all global names
19 * defined by the hash table generator). All further
20 * names mentioned here except for macro names will be
21 * implicitly prefixed.
23 * Then you continue by including "lib/binheap-node.h" which defines struct bh_node
24 * and struct bh_root (both without prefix). The heap elements are always allocated by
25 * you and they must include struct bh_node which serves as a handle used for all
26 * the heap functions and it contains all information needed for heap-keeping.
27 * The heap itself is also allocated by you and it's represented by struct bh_heap.
29 * When you have the declaration of heap nodes, you continue with defining:
31 * less(p,q) returns 1 if the key corresponding to bh_node *p
32 * is less than the one corresponding to *q.
34 * Then specify what operations you request:
36 * <always defined> init(heap*) -- initialize the heap.
37 * BH_WANT_INSERT insert(heap*, node*) -- insert the node to the heap.
38 * BH_WANT_FINDMIN node *findmin(heap*) -- find node with minimum key.
39 * BH_WANT_DELETEMIN node *deletemin(heap*) -- findmin and delete the node.
41 * Then include "lib/binheap.h" and voila, you have a binomial heap
42 * suiting all your needs (at least those which you've revealed :) ).
44 * You also get a iterator macro at no extra charge:
46 * BH_FOR_ALL(bh_prefix, hash*, variable)
48 * // node *variable gets declared automatically
49 * do_something_with_node(variable);
50 * // use BH_BREAK and BH_CONTINUE instead of break and continue
51 * // you must not alter contents of the hash table here
55 * After including this file, all parameter macros are automatically
59 #define BH_NODE struct bh_node
60 #define BH_HEAP struct bh_heap
63 BH_PREFIX(merge)(BH_NODE *a, BH_NODE *b)
65 BH_NODE **pp = &a->first_son;
66 BH_NODE *q = b->first_son;
69 while ((p = *pp) && q)
71 /* p,q are the next nodes of a,b; pp points to where p is linked */
72 if (p->order < q->order) /* p is smaller => skip it */
73 pp = &p->next_sibling;
74 else if (p->order > q->order) /* q is smaller => insert it before p */
80 pp = &r->next_sibling;
82 else /* p and q are of the same order => need to merge them */
84 if (BH_PREFIX(less)(p, q)) /* we'll hang r below s */
94 *pp = p->next_sibling; /* unlink p,q from their lists */
97 if (s->last_son) /* merge r to s, increasing order */
98 s->last_son->next_sibling = r;
103 r->next_sibling = NULL;
105 if (!q || q->order > s->order) /* put the result into the b's list if possible */
110 else /* otherwise put the result to the a's list */
112 p = s->next_sibling = *pp;
114 if (p && p->order == s->order) /* 3-collision */
115 pp = &s->next_sibling;
123 #ifdef BH_WANT_INSERT
125 BH_PREFIX(insert)(BH_HEAP *heap, BH_NODE *a)
130 a->first_son = a->last_son = a->next_sibling = NULL;
131 BH_PREFIX(merge)(&heap->root, &sh);
135 #ifdef BH_WANT_FINDMIN
137 BH_PREFIX(findmin)(BH_HEAP *heap)
142 for (p=heap->root.first_son; p; p=p->next_sibling)
143 if (!best || BH_PREFIX(less)(p, best))
149 #ifdef BH_WANT_DELETEMIN
151 BH_PREFIX(deletemin)(BH_HEAP *heap)
153 BH_NODE *p, **pp, **bestp;
156 for (pp=&heap->root.first_son; p=*pp; pp=&p->next_sibling)
157 if (!bestp || BH_PREFIX(less)(p, *bestp))
163 *bestp = p->next_sibling;
164 BH_PREFIX(merge)(&heap->root, p);
170 BH_PREFIX(init)(BH_HEAP *heap)
172 bzero(heap, sizeof(*heap));
177 #define BH_FOR_ALL(bh_px, bh_heap, bh_var) \
179 struct bh_node *bh_stack[32]; \
181 if (bh_stack[0] = (bh_heap)->root.first_son) \
184 struct bh_node *bh_var = bh_stack[--bh_sp]; \
185 if (bh_var->next_sibling) \
186 bh_stack[bh_sp++] = bh_var->next_sibling; \
187 if (bh_var->first_son) \
188 bh_stack[bh_sp++] = bh_var->first_son;
193 #define BH_BREAK { bh_sp=0; break; }
194 #define BH_CONTINUE continue
201 #undef BH_WANT_INSERT
202 #undef BH_WANT_FINDMIN
203 #undef BH_WANT_DELETEMIN