* Documented binary heaps.
* Documented binomial heaps (missing example).
* Some fixes.
#ifndef _UCW_BINHEAP_NODE_H
#define _UCW_BINHEAP_NODE_H
+/***
+ * [common]
+ * Common definitions
+ * ------------------
+ ***/
+
+/**
+ * Common header of binomial heap nodes.
+ **/
struct bh_node {
struct bh_node *first_son;
struct bh_node *last_son;
byte order;
};
+/**
+ * A binomial heap.
+ **/
struct bh_heap {
struct bh_node root;
};
* this file with parameters set in the corresponding preprocessor macros
* as described below, it generates functions for manipulating the particular
* version of the binomial heap.
+ */
+
+/***
+ * [[generator]]
+ * Interface to the generator
+ * --------------------------
*
- * You need to specify:
+ * To use the binomial heaps, you need to specify:
*
- * BH_PREFIX(x) macro to add a name prefix (used on all global names
- * defined by the hash table generator). All further
- * names mentioned here except for macro names will be
- * implicitly prefixed.
+ * - `BH_PREFIX(x)` -- macro to add a name prefix (used on all global names
+ * defined by the generator). All further names mentioned
+ * here except for macro names will be implicitly prefixed.
*
- * Then you continue by including "ucw/binheap-node.h" which defines struct bh_node
- * and struct bh_root (both without prefix). The heap elements are always allocated by
- * you and they must include struct bh_node which serves as a handle used for all
- * the heap functions and it contains all information needed for heap-keeping.
- * The heap itself is also allocated by you and it's represented by struct bh_heap.
+ * Then you continue by including `ucw/binheap-node.h` which defines <<struct_bh_node,struct bh_node>>
+ * and <<struct_bh_heap,struct bh_heap>> (both without prefix). The heap elements are always allocated by
+ * you and they must include `struct bh_node` which serves as a handle used for all
+ * the heap functions and it contains all information needed for heap-keeping.
+ * The heap itself is also allocated by you and it's represented by `struct bh_heap`.
*
- * When you have the declaration of heap nodes, you continue with defining:
+ * When you have the declaration of heap nodes, you continue with defining:
*
- * less(p,q) returns 1 if the key corresponding to bh_node *p
- * is less than the one corresponding to *q.
+ * - `less(p,q)` -- returns `1` if the key corresponding to `bh_node *p`
+ * is less than the one corresponding to `*q`.
*
- * Then specify what operations you request:
+ * Then specify what operations you request:
*
- * <always defined> init(heap*) -- initialize the heap.
- * BH_WANT_INSERT insert(heap*, node*) -- insert the node to the heap.
- * BH_WANT_FINDMIN node *findmin(heap*) -- find node with minimum key.
- * BH_WANT_DELETEMIN node *deletemin(heap*) -- findmin and delete the node.
+ * - `init(heap\*)` -- initialize the heap (always defined).
+ * - `insert(heap\*, node\*)` -- insert the node to the heap (`BH_WANT_INSERT`).
+ * - `node\* findmin(heap\*)` -- find node with minimum key (`BH_WANT_FINDMIN`).
+ * - `node\* deletemin(heap\*)` -- findmin and delete the node (`BH_WANT_DELETEMIN`).
*
- * Then include "ucw/binheap.h" and voila, you have a binomial heap
- * suiting all your needs (at least those which you've revealed :) ).
+ * Then include `ucw/binheap.h` and voila, you have a binomial heap
+ * suiting all your needs (at least those which you've revealed :) ).
*
- * You also get a iterator macro at no extra charge:
+ * You also get a iterator macro at no extra charge:
*
- * BH_FOR_ALL(bh_prefix, hash*, variable)
- * {
- * // node *variable gets declared automatically
- * do_something_with_node(variable);
- * // use BH_BREAK and BH_CONTINUE instead of break and continue
- * // you must not alter contents of the hash table here
- * }
- * BH_END_FOR;
+ * BH_FOR_ALL(bh_prefix, heap*, variable)
+ * {
+ * // node* variable gets declared automatically
+ * do_something_with_node(variable);
+ * // use BH_BREAK and BH_CONTINUE instead of break and continue
+ * // you must not alter contents of the binomial heap here
+ * }
+ * BH_END_FOR;
*
- * After including this file, all parameter macros are automatically
- * undef'd.
- */
+ * After including this file, all parameter macros are automatically undef'd.
+ ***/
#define BH_NODE struct bh_node
#define BH_HEAP struct bh_heap
s->next_sibling = q;
q = s;
}
- else /* otherwise put the result to the a's list */
+ else /* otherwise put the result to the a's list */
{
p = s->next_sibling = *pp;
*pp = s;
DIRS+=ucw/doc
-UCW_DOCS=fastbuf index config configure install basecode hash docsys conf mempool eltpool mainloop generic growbuf unaligned lists chartype unicode prime binsearch
+UCW_DOCS=fastbuf index config configure install basecode hash docsys conf mempool eltpool mainloop generic growbuf unaligned lists chartype unicode prime binsearch heap binheap
UCW_INDEX=$(o)/ucw/doc/def_index.html
UCW_DOCS_HTML=$(addprefix $(o)/ucw/doc/,$(addsuffix .html,$(UCW_DOCS)))
--- /dev/null
+Binomial heaps
+==============
+
+* <<intro,Introduction>>
+* <<common,Common definitions>>
+* <<generator,Interface to the generator>>
+
+[[intro]]
+Introduction
+------------
+
+Binomial heap is a data structure that supports for example efficient merge of two heaps, insertions, deletions or access to the minimum element.
+All these operations are logarithimc in the worst case. If the merge is not significat, it is usually better to use simplier <<heap:,binary heaps>>.
+
+They are defined in `ucw/binheap.h` as <<generic:,generics generated by preprocessor>>, some common definitions are also in `ucw/binheap-node.h`.
+
+!!ucw/binheap-node.h
+
+!!ucw/binheap.h
* <<defs,Definitions>>
* <<examples,Examples>>
- - <<ex_numbers,Numbers>>
- - <<ex_strings,Strings>>
!!ucw/binsearch.h
for several different cases, for example to find lower elements in a (non-)decreasing array or even to find
elements in a (non-)increasing array.
-[[ex_num]]
-Numbers
-~~~~~~~
-
static int inc[10] = { 1, 4, 4, 5, 6, 10, 11, 20, 25, 50 };
+ static const char *str[5] = { "aaa", "abc", "bflmpsvz", "rep", "rep" };
static int dec[3] = { 5, 2, 1 };
// find the first equal element
printf("%d\n", BIN_SEARCH_GE(inc, 10, 4)); // prints 1
printf("%d\n", BIN_SEARCH_GE(inc, 10, 99)); // prints 10 (not found)
- // find the first greater element
+ // find the last equal element (or -1 if does not exist)
#define CMP_LE(ary, i, x) ((ary[i]) <= (x))
+ int i = BIN_SEARCH_FIRST_GE_CMP(inc, 10, 4, CMP_LE);
+ printf("%d\n", (i && inc[i - 1] == 4) ? i - 1 : -1); // prints 2
+
+ // find the first greater element
printf("%d\n", BIN_SEARCH_FIRST_GE_CMP(inc, 10, 25, CMP_LE)); // prints 9
- // find the last lower or equal element (or -1 if not found)
+ // find the last lower or equal element (or -1 if does not exist)
printf("%d\n", BIN_SEARCH_FIRST_GE_CMP(inc, 10, 25, CMP_LE) - 1); // prints 8
- // find the last lower element (or -1 if not found)
+ // find the last lower element (or -1 if does not exist)
printf("%d\n", BIN_SEARCH_FIRST_GE(inc, 10, 25) - 1); // prints 7
+ // find the first greater or equal string
+ #define CMP_STR(ary, i, x) (strcmp((ary[i]), (x)) < 0)
+ printf("%d\n", BIN_SEARCH_GE_CMP(str, 5, "bfl", CMP_STR)); // prints 2
+
// find the first lower or equal element in the non-increasing array
#define CMP_GT(ary, i, x) ((ary[i]) > (x))
printf("%d\n", BIN_SEARCH_FIRST_GE_CMP(dec, 3, 4, CMP_GT)); // prints 1
-
- // ...
-
-[[ex_str]]
-Strings
-~~~~~~~
-
- static char *str[5] = { "aaa", "abc", "bflmpsvz", "rep", "rep" };
-
- #define CMP_STR(ary, i, x) (strcmp((ary[i]), (x)) < 0)
-
- printf("%d\n", BIN_SEARCH_GE_CMP(str, 5, "bfl", CMP_STR)); // prints 2
--- /dev/null
+Binary heaps
+============
+
+* <<intro,Introduction>>
+* <<macros,Macros>>
+* <<example,Example>>
+
+!!ucw/heap.h
+
+[[example]]
+Example
+-------
+
+ static uns n;
+ static int heap[4];
+
+ // Create an empty heap
+ n = 0;
+ #define MY_CMP(x, y) ((x) < (y))
+
+ // Insert 20, 10, 30
+ heap[n + 1] = 20;
+ HEAP_INSERT(int, heap, n, MY_CMP, HEAP_SWAP);
+ heap[n + 1] = 10;
+ HEAP_INSERT(int, heap, n, MY_CMP, HEAP_SWAP);
+ heap[n + 1] = 30;
+ HEAP_INSERT(int, heap, n, MY_CMP, HEAP_SWAP);
+
+ // Remove the minimum (10)
+ HEAP_DELMIN(int, heap, n, MY_CMP, HEAP_SWAP);
+
+ // Print the new minimum (20)
+ printf("%d", heap[1]);
+
+ // Increase the minimum by 20 to 40
+ heap[1] += 20;
+ HEAP_INCREASE(int, heap, n, MY_CMP, HEAP_SWAP, 1);
+
+ // Print the new minimum (30)
+ printf("%d", heap[1]);
- <<unicode:,Multi-byte characters>>
- <<prime:,Prime numbers>>
- <<binsearch:,Binary search>>
+- <<heap:,Binary heaps>>
+- <<binheap:,Binomial heaps>>
Other features
--------------
------------------------
- Sorting
* `sorter/`
-- Heaps
- * `binheap.h`
- * `binheap-node.h`
- * `heap.h`
- Hash tables
* `hashtable.h`
- Trie
* of the GNU Lesser General Public License.
*/
+/***
+ * [[intro]]
+ * Introduction
+ * ------------
+ *
+ * Binary heap is a simple data structure, which for example supports efficient insertions, deletions
+ * and access to the minimal inserted item. We define several macros for such operations.
+ * Note that because of simplicity of heaps, we have decided to define direct macros instead
+ * of a <<generic:,macro generator>> as for several other data structures in the Libucw.
+ *
+ * A heap is represented by a number of elements and by an array of values. Beware that we
+ * index this array from one, not from zero as do the standard C arrays.
+ *
+ * Most macros use these parameters:
+ *
+ * - @type - the type of elements
+ * - @num - a variable (signed or unsigned integer) with the number of elements
+ * - @heap - a C array of type @type; the heap is stored in `heap[1] .. heap[num]`; `heap[0]` is unused
+ * - @less - a callback to compare two element values; `less(x, y)` shall return a non-zero value iff @x is lower than @y
+ * - @swap - a callback to swap two array elements; `swap(heap, i, j, t)` must swap `heap[i]` with `heap[j]` with possible help of temporary variable @t (type @type).
+ *
+ * A valid heap must follow these rules:
+ *
+ * - `num >= 0`
+ * - `heap[i] >= heap[i / 2]` for each `i` in `[2, num]`
+ *
+ * The first element `heap[1]` is always lower or equal to all other elements.
+ *
+ * [[macros]]
+ * Macros
+ * ------
+ ***/
+
+/* For internal usage. */
#define HEAP_BUBBLE_DOWN_J(heap,num,less,swap) \
for (;;) \
{ \
_j = _l; \
}
+/* For internal usage. */
#define HEAP_BUBBLE_UP_J(heap,num,less,swap) \
while (_j > 1) \
{ \
_j = _u; \
}
+/**
+ * Shuffle the unordered array @heap of @num elements to become a valid heap. The time complexity is linear.
+ **/
#define HEAP_INIT(type,heap,num,less,swap) \
do { \
uns _i = num; \
} \
} while(0)
+/**
+ * Delete the minimum element `heap[1]` in `O(log(n))` time.
+ * The removed value is moved just after the resulting heap (`heap[num + 1]`).
+ **/
#define HEAP_DELMIN(type,heap,num,less,swap) \
do { \
uns _j, _l; \
type x; \
swap(heap,1,num,x); \
- num--; \
+ num--; \
_j = 1; \
HEAP_BUBBLE_DOWN_J(heap,num,less,swap); \
} while(0)
+/**
+ * Insert `heap[num + 1]` in `O(log(n))` time.
+ **/
#define HEAP_INSERT(type,heap,num,less,swap) \
do { \
uns _j, _u; \
HEAP_BUBBLE_UP_J(heap,num,less,swap); \
} while(0)
+/**
+ * If you need to increase the value of `heap[pos]`, just do it and then call this macro to rebuild the heap.
+ * Only `heap[pos]` can be changed, the rest of the array must form a valid heap.
+ * The time complexity is `O(log(n))`.
+ **/
#define HEAP_INCREASE(type,heap,num,less,swap,pos) \
do { \
uns _j, _l; \
HEAP_BUBBLE_DOWN_J(heap,num,less,swap); \
} while(0)
+/**
+ * Delete `heap[pos]` in `O(log(n))` time.
+ **/
#define HEAP_DELETE(type,heap,num,less,swap,pos) \
do { \
uns _j, _l, _u; \
HEAP_BUBBLE_DOWN_J(heap,num,less,swap); \
} while(0)
-/* Default swapping macro */
+/**
+ * Default swapping macro.
+ **/
#define HEAP_SWAP(heap,a,b,t) (t=heap[a], heap[a]=heap[b], heap[b]=t)