libdict 1.0.7
Data Structure C Library
Loading...
Searching...
No Matches
tr_tree.c
Go to the documentation of this file.
1/*
2 * libdict -- treap implementation.
3 *
4 * Copyright (c) 2001-2014, Farooq Mela
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/*
29 * cf. [Aragon and Seidel, 1996], [Knuth 1998]
30 *
31 * A treap is a randomized data structure in which each node of the tree has
32 * an associated key and priority. The priority is chosen at random when the
33 * node is inserted into the tree, unless a dict_prio_func supplies it. Each
34 * node is inserted so that the lexicographic order of the keys is preserved,
35 * and the priority of any node is greater than or equal to the priority of
36 * either of its child nodes; in this way the treap is a combination of a tree
37 * and a max-heap. Note the direction: a dict_prio_func should return a LARGER
38 * value for a key that ought to sit closer to the root. In this
39 * implementation, this is accomplished by first inserting the node according
40 * to the lexicographical order of keys as in a normal binary tree, and then,
41 * if needed, sifting the node upwards using a series of rotations until the
42 * heap property of the tree is restored.
43 */
44
45#include "tr_tree.h"
46
47#include "dict_private.h"
48#include "tree_common.h"
49
50typedef struct tr_node tr_node;
51struct tr_node {
53 uint32_t prio;
54};
55
60
64
65/* Vtable thunks. The vtable slot types take void*, and calling a function
66 * through a function-pointer type that is not compatible with the function's
67 * own type is undefined behaviour (C11 6.5.2.2p9), so each slot below gets a
68 * thunk with the exact slot signature instead of a cast. A cast would also
69 * hide a genuine signature mismatch. */
70static dict_itor* vt_tr_dict_itor_new(void* obj) { return tr_dict_itor_new(obj); }
71static dict_insert_result vt_tr_tree_insert(void* obj, void* key) { return tr_tree_insert(obj, key); }
72static dict_remove_result vt_tr_tree_remove(void* obj, const void* key) { return tr_tree_remove(obj, key); }
73static bool vt_tr_tree_verify(const void* obj) { return tr_tree_verify(obj); }
74static bool vt_tr_itor_remove(void* itor) { return tr_itor_remove(itor); }
75
76static const dict_vtable tr_tree_vtable = {
77 true,
78 vt_tr_dict_itor_new,
80 vt_tr_tree_insert,
86 vt_tr_tree_remove,
91 vt_tr_tree_verify,
92};
93
94static const itor_vtable tr_tree_itor_vtable = {
111 vt_tr_itor_remove,
113};
114
115static tr_node* node_new(void* key);
116
117tr_tree*
119{
120 ASSERT(cmp_func != NULL);
121
122 tr_tree* tree = MALLOC(sizeof(*tree));
123 if (tree) {
124 tree->root = NULL;
125 tree->count = 0;
126 tree->cmp_func = cmp_func;
127 tree->rotation_count = 0;
128 tree->prio_func = prio_func;
129 }
130 return tree;
131}
132
133dict*
135{
136 dict* dct = MALLOC(sizeof(*dct));
137 if (dct) {
138 if (!(dct->_object = tr_tree_new(cmp_func, prio_func))) {
139 FREE(dct);
140 return NULL;
141 }
142 dct->_vtable = &tr_tree_vtable;
143 }
144 return dct;
145}
146
147size_t tr_tree_free(tr_tree* tree, dict_delete_func delete_func) { return tree_free(tree, delete_func); }
148size_t tr_tree_clear(tr_tree* tree, dict_delete_func delete_func) { return tree_clear(tree, delete_func); }
149
152{
153 int cmp = 0;
154 tr_node* node = tree->root;
155 tr_node* parent = NULL;
156 while (node) {
157 cmp = tree->cmp_func(key, node->key);
158 if (cmp < 0) {
159 parent = node; node = node->llink;
160 } else if (cmp > 0) {
161 parent = node; node = node->rlink;
162 } else
163 return (dict_insert_result) { &node->datum, false };
164 }
165
166 if (!(node = node_new(key)))
167 return (dict_insert_result) { NULL, false };
168 node->prio = tree->prio_func ? tree->prio_func(key) : dict_rand();
169
170 if (!(node->parent = parent)) {
171 ASSERT(tree->root == NULL);
172 ASSERT(tree->count == 0);
173 tree->root = node;
174 } else {
175 if (cmp < 0)
176 parent->llink = node;
177 else
178 parent->rlink = node;
179
180 unsigned rotations = 0;
181 while (parent->prio < node->prio) {
182 ++rotations;
183 if (parent->llink == node)
184 tree_node_rot_right(tree, parent);
185 else
186 tree_node_rot_left(tree, parent);
187 if (!(parent = node->parent))
188 break;
189 }
190 tree->rotation_count += rotations;
191 }
192 tree->count++;
193 return (dict_insert_result) { &node->datum, true };
194}
195
196static void
197remove_node(tr_tree* tree, tr_node* node)
198{
199 unsigned rotations = 0;
200 while (node->llink && node->rlink) {
201 ++rotations;
202 if (node->llink->prio > node->rlink->prio)
204 else
206 }
207 tree->rotation_count += rotations;
208
209 tr_node* const out = node->llink ? node->llink : node->rlink;
210 tr_node* const parent = node->parent;
211 if (out)
212 out->parent = parent;
213 *(parent ? (parent->llink == node ? &parent->llink : &parent->rlink) : &tree->root) = out;
214
215 FREE(node);
216 tree->count--;
217}
218
220tr_tree_remove(tr_tree* tree, const void* key)
221{
222 tr_node* node = tree_search_node(tree, key);
223 if (!node)
224 return (dict_remove_result) { NULL, NULL, false };
225 dict_remove_result result = { node->key, node->datum, true };
226 remove_node(tree, node);
227 return result;
228}
229
230void** tr_tree_search(tr_tree* tree, const void* key) { return tree_search(tree, key); }
231void** tr_tree_search_le(tr_tree* tree, const void* key) { return tree_search_le(tree, key); }
232void** tr_tree_search_lt(tr_tree* tree, const void* key) { return tree_search_lt(tree, key); }
233void** tr_tree_search_ge(tr_tree* tree, const void* key) { return tree_search_ge(tree, key); }
234void** tr_tree_search_gt(tr_tree* tree, const void* key) { return tree_search_gt(tree, key); }
235size_t tr_tree_traverse(tr_tree* tree, dict_visit_func visit, void* user_data) { return tree_traverse(tree, visit, user_data); }
236bool tr_tree_select(tr_tree* tree, size_t n, const void** key, void** datum) { return tree_select(tree, n, key, datum); }
237size_t tr_tree_count(const tr_tree* tree) { return tree_count(tree); }
241
242static tr_node*
243node_new(void* key)
244{
245 tr_node* node = MALLOC(sizeof(*node));
246 if (node) {
247 node->key = key;
248 node->datum = NULL;
249 node->parent = NULL;
250 node->llink = NULL;
251 node->rlink = NULL;
252 /* Overwritten by the caller, but leaving it uninitialized would make a
253 * future second caller inherit heap garbage as a priority. */
254 node->prio = 0;
255 }
256 return node;
257}
258
259bool
261{
262 /* Search-tree, parent-link and count invariants. Iterative, because a
263 * treap given a poor priority function degenerates into a chain as deep
264 * as it has nodes. */
266 return false;
267
268 /* Max-heap property on priorities. Now that the links have been verified
269 * an in-order walk is safe, and it needs no stack of its own. */
270 const tr_node* node = tree->root;
271 while (node && node->llink)
272 node = node->llink;
273 while (node) {
274 if (node->parent)
275 VERIFY(node->prio <= node->parent->prio);
276 if (node->rlink) {
277 node = node->rlink;
278 while (node->llink)
279 node = node->llink;
280 } else {
281 const tr_node* parent = node->parent;
282 while (parent && parent->rlink == node) {
283 node = parent;
284 parent = parent->parent;
285 }
286 node = parent;
287 }
288 }
289 return true;
290}
291
292tr_itor*
294{
295 tr_itor* itor = MALLOC(sizeof(*itor));
296 if (itor) {
297 itor->tree = tree;
298 itor->node = NULL;
299 }
300 return itor;
301}
302
305{
306 dict_itor* itor = MALLOC(sizeof(*itor));
307 if (itor) {
308 if (!(itor->_itor = tr_itor_new(tree))) {
309 FREE(itor);
310 return NULL;
311 }
312 itor->_vtable = &tr_tree_itor_vtable;
313 }
314 return itor;
315}
316
318bool tr_itor_valid(const tr_itor* itor) { return tree_iterator_valid(itor); }
320bool tr_itor_next(tr_itor* itor) { return tree_iterator_next(itor); }
321bool tr_itor_prev(tr_itor* itor) { return tree_iterator_prev(itor); }
322bool tr_itor_nextn(tr_itor* itor, size_t count) { return tree_iterator_nextn(itor, count); }
323bool tr_itor_prevn(tr_itor* itor, size_t count) { return tree_iterator_prevn(itor, count); }
324bool tr_itor_first(tr_itor* itor) { return tree_iterator_first(itor); }
325bool tr_itor_last(tr_itor* itor) { return tree_iterator_last(itor); }
326bool tr_itor_search(tr_itor* itor, const void* key) { return tree_iterator_search(itor, key); }
327bool tr_itor_search_le(tr_itor* itor, const void* key) { return tree_iterator_search_le(itor, key); }
328bool tr_itor_search_lt(tr_itor* itor, const void* key) { return tree_iterator_search_lt(itor, key); }
329bool tr_itor_search_ge(tr_itor* itor, const void* key) { return tree_iterator_search_ge(itor, key); }
330bool tr_itor_search_gt(tr_itor* itor, const void* key) { return tree_iterator_search_gt(itor, key); }
331const void* tr_itor_key(const tr_itor* itor) { return tree_iterator_key(itor); }
332void** tr_itor_datum(tr_itor* itor) { return tree_iterator_datum(itor); }
333int tr_itor_compare(const tr_itor* i1, const tr_itor* i2) { return tree_iterator_compare(i1, i2); }
334
335bool
337{
338 if (!it->node)
339 return false;
340 remove_node(it->tree, it->node);
341 it->node = NULL;
342 return true;
343}
int(* dict_compare_func)(const void *, const void *)
A pointer to a function that compares two keys.
Definition dict.h:59
void(* dict_delete_func)(void *, void *)
A pointer to a function that is called when a key-value pair gets removed from a dictionary.
Definition dict.h:62
unsigned(* dict_prio_func)(const void *)
A pointer to a function that returns the priority of a key, used by tr_tree (a treap).
Definition dict.h:70
bool(* dict_visit_func)(const void *, void *, void *)
A pointer to a function used for iterating over dictionary contents.
Definition dict.h:64
#define FREE(p)
#define ASSERT(expr)
#define VERIFY(expr)
#define MALLOC(n)
void * _itor
Definition dict.h:235
const itor_vtable * _vtable
Definition dict.h:236
The operations of one container type.
Definition dict.h:110
Definition dict.h:164
void * _object
Definition dict.h:165
const dict_vtable * _vtable
Definition dict.h:166
tr_node * node
Definition tr_tree.c:62
tr_tree * tree
Definition tr_tree.c:62
tr_node * parent
Definition tr_tree.c:52
void * datum
Definition tr_tree.c:52
uint32_t prio
Definition tr_tree.c:53
void * key
Definition tr_tree.c:52
tr_node * llink
Definition tr_tree.c:52
tr_node * rlink
Definition tr_tree.c:52
dict_prio_func prio_func
Definition tr_tree.c:58
dict_compare_func cmp_func
Definition tree_common.c:38
tree_node * root
Definition tree_common.c:38
size_t count
Definition tree_common.c:38
size_t rotation_count
Definition tree_common.c:38
void ** tr_itor_datum(tr_itor *itor)
Return the address of the datum |itor| is positioned on, through which it can be read or replaced,...
Definition tr_tree.c:332
bool tr_itor_search_le(tr_itor *itor, const void *key)
Position |itor| on the greatest key less than or equal to |key| and return true, or unposition it and...
Definition tr_tree.c:327
dict_itor * tr_dict_itor_new(tr_tree *tree)
Like tr_itor_new(), but wrapped in a generic dict_itor for use with the dict_itor_* macros.
Definition tr_tree.c:304
dict_remove_result tr_tree_remove(tr_tree *tree, const void *key)
Remove the element with key |key|.
Definition tr_tree.c:220
bool tr_itor_remove(tr_itor *it)
Remove the element |itor| is positioned on and unposition |itor|; return false if it was not position...
Definition tr_tree.c:336
size_t tr_tree_total_path_length(const tr_tree *tree)
Return the sum of the depths of all nodes, the root being at depth 1, or 0 for an empty tree.
Definition tr_tree.c:240
void tr_itor_invalidate(tr_itor *itor)
Unposition |itor|, so that it is not positioned on any element.
Definition tr_tree.c:319
tr_tree * tr_tree_new(dict_compare_func cmp_func, dict_prio_func prio_func)
Create an empty treap that orders keys with |compare_func| (must not be NULL) and takes node prioriti...
Definition tr_tree.c:118
bool tr_tree_select(tr_tree *tree, size_t n, const void **key, void **datum)
Store the key and datum of the |n|th element in key order (0-based) through |key| and |datum| and ret...
Definition tr_tree.c:236
bool tr_itor_last(tr_itor *itor)
Position |itor| on the last element in key order and return true, or unposition it and return false i...
Definition tr_tree.c:325
bool tr_itor_search_lt(tr_itor *itor, const void *key)
Position |itor| on the greatest key less than |key| and return true, or unposition it and return fals...
Definition tr_tree.c:328
void ** tr_tree_search_le(tr_tree *tree, const void *key)
Return the address of the datum of the greatest key less than or equal to |key|, or NULL if there is ...
Definition tr_tree.c:231
bool tr_itor_nextn(tr_itor *itor, size_t count)
Move |itor| |count| elements forward and return whether it is still positioned.
Definition tr_tree.c:322
size_t tr_tree_clear(tr_tree *tree, dict_delete_func delete_func)
Remove every element, calling |delete_func|(key, datum) for each unless |delete_func| is NULL.
Definition tr_tree.c:148
bool tr_itor_next(tr_itor *itor)
Move |itor| to the next element in key order and return true, or unposition it and return false if th...
Definition tr_tree.c:320
size_t tr_tree_traverse(tr_tree *tree, dict_visit_func visit, void *user_data)
Call |visit|(key, datum, |user_data|) for each element in key order, stopping early if |visit| return...
Definition tr_tree.c:235
size_t tr_tree_free(tr_tree *tree, dict_delete_func delete_func)
Remove every element, calling |delete_func|(key, datum) for each unless |delete_func| is NULL,...
Definition tr_tree.c:147
bool tr_itor_first(tr_itor *itor)
Position |itor| on the first element in key order and return true, or unposition it and return false ...
Definition tr_tree.c:324
tr_itor * tr_itor_new(tr_tree *tree)
Create an iterator over |tree| that is not positioned on any element yet.
Definition tr_tree.c:293
bool tr_itor_prev(tr_itor *itor)
Move |itor| to the previous element in key order and return true, or unposition it and return false i...
Definition tr_tree.c:321
bool tr_itor_search_ge(tr_itor *itor, const void *key)
Position |itor| on the least key greater than or equal to |key| and return true, or unposition it and...
Definition tr_tree.c:329
size_t tr_tree_min_path_length(const tr_tree *tree)
Return the shallowest depth at which a child link is absent, the root being at depth 1,...
Definition tr_tree.c:238
bool tr_itor_search_gt(tr_itor *itor, const void *key)
Position |itor| on the least key greater than |key| and return true, or unposition it and return fals...
Definition tr_tree.c:330
const void * tr_itor_key(const tr_itor *itor)
Return the key |itor| is positioned on, or NULL if it is not positioned.
Definition tr_tree.c:331
bool tr_itor_valid(const tr_itor *itor)
Return whether |itor| is positioned on an element.
Definition tr_tree.c:318
bool tr_tree_verify(const tr_tree *tree)
Check the internal invariants of the tree and return true if they hold, or print the first failed che...
Definition tr_tree.c:260
bool tr_itor_prevn(tr_itor *itor, size_t count)
Move |itor| |count| elements back and return whether it is still positioned.
Definition tr_tree.c:323
void tr_itor_free(tr_itor *itor)
Free an iterator.
Definition tr_tree.c:317
dict * tr_dict_new(dict_compare_func cmp_func, dict_prio_func prio_func)
Like tr_tree_new(), but wrapped in a generic dict for use with the dict_* macros.
Definition tr_tree.c:134
size_t tr_tree_count(const tr_tree *tree)
Return the number of elements.
Definition tr_tree.c:237
int tr_itor_compare(const tr_itor *i1, const tr_itor *i2)
Compare the positions of two iterators over the same tree: return a negative value,...
Definition tr_tree.c:333
void ** tr_tree_search_lt(tr_tree *tree, const void *key)
Return the address of the datum of the greatest key less than |key|, or NULL if there is none.
Definition tr_tree.c:232
void ** tr_tree_search_ge(tr_tree *tree, const void *key)
Return the address of the datum of the least key greater than or equal to |key|, or NULL if there is ...
Definition tr_tree.c:233
void ** tr_tree_search_gt(tr_tree *tree, const void *key)
Return the address of the datum of the least key greater than |key|, or NULL if there is none.
Definition tr_tree.c:234
dict_insert_result tr_tree_insert(tr_tree *tree, void *key)
Insert |key| unless an equal key is present.
Definition tr_tree.c:151
bool tr_itor_search(tr_itor *itor, const void *key)
Position |itor| on |key| and return true, or unposition it and return false if |key| is not present.
Definition tr_tree.c:326
size_t tr_tree_max_path_length(const tr_tree *tree)
Return the greatest depth of any node, the root being at depth 1, or 0 for an empty tree: the height ...
Definition tr_tree.c:239
void ** tr_tree_search(tr_tree *tree, const void *key)
Return the address of the datum stored for |key|, or NULL if |key| is not present.
Definition tr_tree.c:230
Treap: a binary search tree on the keys that is at the same time a max-heap on per-node priorities.
bool tree_iterator_last(void *Iterator)
size_t tree_free(void *Tree, dict_delete_func delete_func)
void ** tree_iterator_datum(void *Iterator)
bool tree_iterator_next(void *Iterator)
void tree_iterator_invalidate(void *Iterator)
void ** tree_search_gt(void *Tree, const void *key)
int tree_iterator_compare(const void *Iterator1, const void *Iterator2)
void tree_node_rot_left(void *Tree, void *Node)
Definition tree_common.c:46
void * tree_search_node(void *Tree, const void *key)
bool tree_verify_common(const void *Tree)
bool tree_iterator_search_le(void *Iterator, const void *key)
bool tree_iterator_valid(const void *Iterator)
size_t tree_count(const void *Tree)
void ** tree_search_lt(void *Tree, const void *key)
size_t tree_clear(void *Tree, dict_delete_func delete_func)
const void * tree_iterator_key(const void *Iterator)
size_t tree_min_path_length(const void *Tree)
void ** tree_search(void *Tree, const void *key)
bool tree_iterator_nextn(void *Iterator, size_t count)
size_t tree_traverse(void *Tree, dict_visit_func visit, void *user_data)
size_t tree_total_path_length(const void *Tree)
bool tree_iterator_first(void *Iterator)
bool tree_select(void *Tree, size_t n, const void **key, void **datum)
void tree_iterator_free(void *Iterator)
bool tree_iterator_prevn(void *Iterator, size_t count)
bool tree_iterator_search_lt(void *Iterator, const void *key)
bool tree_iterator_search_ge(void *Iterator, const void *key)
size_t tree_max_path_length(const void *Tree)
void * tree_iterator_key_vt(void *Iterator)
int tree_iterator_compare_vt(void *Iterator1, void *Iterator2)
bool tree_iterator_search_gt(void *Iterator, const void *key)
void ** tree_search_ge(void *Tree, const void *key)
void tree_node_rot_right(void *Tree, void *Node)
Definition tree_common.c:62
void ** tree_search_le(void *Tree, const void *key)
bool tree_iterator_search(void *Iterator, const void *key)
bool tree_iterator_prev(void *Iterator)
#define TREE_NODE_FIELDS(node_type)
Definition tree_common.h:33
#define TREE_ITERATOR_FIELDS(tree_type, node_type)
Definition tree_common.h:54
#define TREE_FIELDS(node_type)
Definition tree_common.h:44