rbtree3 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (10) hide show
  1. checksums.yaml +7 -0
  2. data/ChangeLog +492 -0
  3. data/LICENSE +22 -0
  4. data/README +106 -0
  5. data/dict.c +1216 -0
  6. data/dict.h +123 -0
  7. data/extconf.rb +13 -0
  8. data/rbtree.c +1701 -0
  9. data/test.rb +950 -0
  10. metadata +64 -0
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2002-2004, 2007, 2009 OZAWA Takuma
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,106 @@
1
+ =begin
2
+
3
+ = Ruby/RBTree
4
+
5
+ RBTree is a sorted associative collection that is implemented with
6
+ Red-Black Tree. The elements of RBTree are ordered and its interface
7
+ is the almost same as Hash, so simply you can consider RBTree sorted
8
+ Hash.
9
+
10
+ Red-Black Tree is a kind of binary tree that automatically balances
11
+ by itself when a node is inserted or deleted. Thus the complexity
12
+ for insert, search and delete is O(log N) in expected and worst
13
+ case. On the other hand the complexity of Hash is O(1). Because
14
+ Hash is unordered the data structure is more effective than
15
+ Red-Black Tree as an associative collection.
16
+
17
+ The elements of RBTree are sorted with natural ordering (by <=>
18
+ method) of its keys or by a comparator(Proc) set by readjust
19
+ method. It means all keys in RBTree should be comparable with each
20
+ other. Or a comparator that takes two arguments of a key should return
21
+ negative, 0, or positive depending on the first argument is less than,
22
+ equal to, or greater than the second one.
23
+
24
+ The interface of RBTree is the almost same as Hash and there are a
25
+ few methods to take advantage of the ordering:
26
+
27
+ * lower_bound, upper_bound, bound
28
+ * first, last
29
+ * shift, pop
30
+ * reverse_each
31
+
32
+ Note: while iterating RBTree (e.g. in a block of each method), it is
33
+ not modifiable, or TypeError is thrown.
34
+
35
+ RBTree supoorts pretty printing using pp.
36
+
37
+ This library contains two classes. One is RBTree and the other is
38
+ MultiRBTree that is a parent class of RBTree. RBTree does not allow
39
+ duplications of keys but MultiRBTree does.
40
+
41
+ require "rbtree"
42
+
43
+ rbtree = RBTree["c", 10, "a", 20]
44
+ rbtree["b"] = 30
45
+ p rbtree["b"] # => 30
46
+ rbtree.each do |k, v|
47
+ p [k, v]
48
+ end # => ["a", 20] ["b", 30] ["c", 10]
49
+
50
+ mrbtree = MultiRBTree["c", 10, "a", 20, "e", 30, "a", 40]
51
+ p mrbtree.lower_bound("b") # => ["c", 10]
52
+ mrbtree.bound("a", "d") do |k, v|
53
+ p [k, v]
54
+ end # => ["a", 20] ["a", 40] ["c", 10]
55
+
56
+ == Requirement
57
+
58
+ * Ruby 1.8.x
59
+
60
+ == Install
61
+
62
+ $ sudo gem install rbtree
63
+
64
+ or download a tarball from the link below
65
+
66
+ * ((<"Ruby/RBTree 0.2.1"|URL:rbtree-0.2.1.tar.gz>))
67
+
68
+ and then
69
+
70
+ $ tar xzf rbtree-x.x.x.tar.gz
71
+ $ cd rbtree-x.x.x.tar.gz
72
+ $ ruby extconf.rb
73
+ $ make
74
+ $ sudo make site-install
75
+
76
+ == Test
77
+
78
+ $ ruby test.rb
79
+
80
+ == Incomplete Documents
81
+
82
+ $ rdoc rbtree.c
83
+
84
+ or online documents at ((<URL:http://rbtree.rubyforge.org/>)).
85
+
86
+ == License
87
+
88
+ MIT License. Copyright (c) 2002-2004, 2007, 2009 OZAWA Takuma.
89
+
90
+ dict.c and dict.h are modified copies that are originally in Kazlib
91
+ written by Kaz Kylheku. Copyright is held by Kaz Kylheku, see dict.c
92
+ and dict.h for the license. The web page of Kazlib is at
93
+ ((<URL:http://users.footprints.net/~kaz/kazlib.html>)).
94
+
95
+ == Support
96
+
97
+ Bug fixes, suggestions and other feedbacks are welcomed. Please mail
98
+ me at burningdowntheopera at yahoo dot co dot jp.
99
+
100
+ == Links
101
+
102
+ * ((<RAA - ruby-rbtree|URL:http://raa.ruby-lang.org/project/ruby-rbtree/>))
103
+ * ((<RubyForge: rbtree: Project Info|URL:http://rubyforge.org/projects/rbtree/>))
104
+ * ((<URL:http://www.geocities.co.jp/SiliconValley-PaloAlto/3388/rbtree/README.html>))
105
+
106
+ =end
data/dict.c ADDED
@@ -0,0 +1,1216 @@
1
+ /*
2
+ * Dictionary Abstract Data Type
3
+ * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
4
+ *
5
+ * Free Software License:
6
+ *
7
+ * All rights are reserved by the author, with the following exceptions:
8
+ * Permission is granted to freely reproduce and distribute this software,
9
+ * possibly in exchange for a fee, provided that this copyright notice appears
10
+ * intact. Permission is also granted to adapt this software to produce
11
+ * derivative works, as long as the modified versions carry this copyright
12
+ * notice and additional notices stating that the work has been modified.
13
+ * This source code may be translated into executable form and incorporated
14
+ * into proprietary software; there is no requirement for such software to
15
+ * contain a copyright notice related to this source.
16
+ *
17
+ * $Id: dict.c,v 1.15 2005/10/06 05:16:35 kuma Exp $
18
+ * $Name: $
19
+ */
20
+
21
+ /*
22
+ * Modified for Ruby/RBTree by OZAWA Takuma.
23
+ */
24
+
25
+ #include <stdlib.h>
26
+ #include <stddef.h>
27
+ #include <assert.h>
28
+ #include "dict.h"
29
+
30
+ #include <ruby.h>
31
+
32
+ #ifdef KAZLIB_RCSID
33
+ static const char rcsid[] = "$Id: dict.c,v 1.15 2005/10/06 05:16:35 kuma Exp $";
34
+ #endif
35
+
36
+ /*
37
+ * These macros provide short convenient names for structure members,
38
+ * which are embellished with dict_ prefixes so that they are
39
+ * properly confined to the documented namespace. It's legal for a
40
+ * program which uses dict to define, for instance, a macro called ``parent''.
41
+ * Such a macro would interfere with the dnode_t struct definition.
42
+ * In general, highly portable and reusable C modules which expose their
43
+ * structures need to confine structure member names to well-defined spaces.
44
+ * The resulting identifiers aren't necessarily convenient to use, nor
45
+ * readable, in the implementation, however!
46
+ */
47
+
48
+ #define left dict_left
49
+ #define right dict_right
50
+ #define parent dict_parent
51
+ #define color dict_color
52
+ #define key dict_key
53
+ #define data dict_data
54
+
55
+ #define nilnode dict_nilnode
56
+ #define nodecount dict_nodecount
57
+ #define compare dict_compare
58
+ #define allocnode dict_allocnode
59
+ #define freenode dict_freenode
60
+ #define context dict_context
61
+ #define dupes dict_dupes
62
+
63
+ #define dictptr dict_dictptr
64
+
65
+ #define dict_root(D) ((D)->nilnode.left)
66
+ #define dict_nil(D) (&(D)->nilnode)
67
+ #define DICT_DEPTH_MAX 64
68
+
69
+ #define COMPARE(dict, key1, key2) dict->compare(key1, key2, dict->context)
70
+
71
+ static dnode_t *dnode_alloc(void *context);
72
+ static void dnode_free(dnode_t *node, void *context);
73
+
74
+ /*
75
+ * Perform a ``left rotation'' adjustment on the tree. The given node P and
76
+ * its right child C are rearranged so that the P instead becomes the left
77
+ * child of C. The left subtree of C is inherited as the new right subtree
78
+ * for P. The ordering of the keys within the tree is thus preserved.
79
+ */
80
+
81
+ static void rotate_left(dnode_t *upper)
82
+ {
83
+ dnode_t *lower, *lowleft, *upparent;
84
+
85
+ lower = upper->right;
86
+ upper->right = lowleft = lower->left;
87
+ lowleft->parent = upper;
88
+
89
+ lower->parent = upparent = upper->parent;
90
+
91
+ /* don't need to check for root node here because root->parent is
92
+ the sentinel nil node, and root->parent->left points back to root */
93
+
94
+ if (upper == upparent->left) {
95
+ upparent->left = lower;
96
+ } else {
97
+ assert (upper == upparent->right);
98
+ upparent->right = lower;
99
+ }
100
+
101
+ lower->left = upper;
102
+ upper->parent = lower;
103
+ }
104
+
105
+ /*
106
+ * This operation is the ``mirror'' image of rotate_left. It is
107
+ * the same procedure, but with left and right interchanged.
108
+ */
109
+
110
+ static void rotate_right(dnode_t *upper)
111
+ {
112
+ dnode_t *lower, *lowright, *upparent;
113
+
114
+ lower = upper->left;
115
+ upper->left = lowright = lower->right;
116
+ lowright->parent = upper;
117
+
118
+ lower->parent = upparent = upper->parent;
119
+
120
+ if (upper == upparent->right) {
121
+ upparent->right = lower;
122
+ } else {
123
+ assert (upper == upparent->left);
124
+ upparent->left = lower;
125
+ }
126
+
127
+ lower->right = upper;
128
+ upper->parent = lower;
129
+ }
130
+
131
+ /*
132
+ * Do a postorder traversal of the tree rooted at the specified
133
+ * node and free everything under it. Used by dict_free().
134
+ */
135
+
136
+ static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
137
+ {
138
+ if (node == nil)
139
+ return;
140
+ free_nodes(dict, node->left, nil);
141
+ free_nodes(dict, node->right, nil);
142
+ dict->freenode(node, dict->context);
143
+ }
144
+
145
+ /*
146
+ * This procedure performs a verification that the given subtree is a binary
147
+ * search tree. It performs an inorder traversal of the tree using the
148
+ * dict_next() successor function, verifying that the key of each node is
149
+ * strictly lower than that of its successor, if duplicates are not allowed,
150
+ * or lower or equal if duplicates are allowed. This function is used for
151
+ * debugging purposes.
152
+ */
153
+
154
+ static int verify_bintree(dict_t *dict)
155
+ {
156
+ dnode_t *first, *next;
157
+
158
+ first = dict_first(dict);
159
+
160
+ if (dict->dupes) {
161
+ while (first && (next = dict_next(dict, first))) {
162
+ if (COMPARE(dict, first->key, next->key) > 0)
163
+ return 0;
164
+ first = next;
165
+ }
166
+ } else {
167
+ while (first && (next = dict_next(dict, first))) {
168
+ if (COMPARE(dict, first->key, next->key) >= 0)
169
+ return 0;
170
+ first = next;
171
+ }
172
+ }
173
+ return 1;
174
+ }
175
+
176
+
177
+ /*
178
+ * This function recursively verifies that the given binary subtree satisfies
179
+ * three of the red black properties. It checks that every red node has only
180
+ * black children. It makes sure that each node is either red or black. And it
181
+ * checks that every path has the same count of black nodes from root to leaf.
182
+ * It returns the blackheight of the given subtree; this allows blackheights to
183
+ * be computed recursively and compared for left and right siblings for
184
+ * mismatches. It does not check for every nil node being black, because there
185
+ * is only one sentinel nil node. The return value of this function is the
186
+ * black height of the subtree rooted at the node ``root'', or zero if the
187
+ * subtree is not red-black.
188
+ */
189
+
190
+ static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
191
+ {
192
+ unsigned height_left, height_right;
193
+
194
+ if (root != nil) {
195
+ height_left = verify_redblack(nil, root->left);
196
+ height_right = verify_redblack(nil, root->right);
197
+ if (height_left == 0 || height_right == 0)
198
+ return 0;
199
+ if (height_left != height_right)
200
+ return 0;
201
+ if (root->color == dnode_red) {
202
+ if (root->left->color != dnode_black)
203
+ return 0;
204
+ if (root->right->color != dnode_black)
205
+ return 0;
206
+ return height_left;
207
+ }
208
+ if (root->color != dnode_black)
209
+ return 0;
210
+ return height_left + 1;
211
+ }
212
+ return 1;
213
+ }
214
+
215
+ /*
216
+ * Compute the actual count of nodes by traversing the tree and
217
+ * return it. This could be compared against the stored count to
218
+ * detect a mismatch.
219
+ */
220
+
221
+ static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root)
222
+ {
223
+ if (root == nil)
224
+ return 0;
225
+ else
226
+ return 1 + verify_node_count(nil, root->left)
227
+ + verify_node_count(nil, root->right);
228
+ }
229
+
230
+ /*
231
+ * Verify that the tree contains the given node. This is done by
232
+ * traversing all of the nodes and comparing their pointers to the
233
+ * given pointer. Returns 1 if the node is found, otherwise
234
+ * returns zero. It is intended for debugging purposes.
235
+ */
236
+
237
+ static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
238
+ {
239
+ if (root != nil) {
240
+ return root == node
241
+ || verify_dict_has_node(nil, root->left, node)
242
+ || verify_dict_has_node(nil, root->right, node);
243
+ }
244
+ return 0;
245
+ }
246
+
247
+
248
+ /*
249
+ * Dynamically allocate and initialize a dictionary object.
250
+ */
251
+
252
+ dict_t *dict_create(dict_comp_t comp)
253
+ {
254
+ dict_t* new = ALLOC(dict_t);
255
+
256
+ if (new) {
257
+ new->compare = comp;
258
+ new->allocnode = dnode_alloc;
259
+ new->freenode = dnode_free;
260
+ new->context = NULL;
261
+ new->nodecount = 0;
262
+ new->nilnode.left = &new->nilnode;
263
+ new->nilnode.right = &new->nilnode;
264
+ new->nilnode.parent = &new->nilnode;
265
+ new->nilnode.color = dnode_black;
266
+ new->dupes = 0;
267
+ }
268
+ return new;
269
+ }
270
+
271
+ /*
272
+ * Select a different set of node allocator routines.
273
+ */
274
+
275
+ void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
276
+ dnode_free_t fr, void *context)
277
+ {
278
+ assert (dict_count(dict) == 0);
279
+ assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL));
280
+
281
+ dict->allocnode = al ? al : dnode_alloc;
282
+ dict->freenode = fr ? fr : dnode_free;
283
+ dict->context = context;
284
+ }
285
+
286
+ /*
287
+ * Free a dynamically allocated dictionary object. Removing the nodes
288
+ * from the tree before deleting it is required.
289
+ */
290
+
291
+ void dict_destroy(dict_t *dict)
292
+ {
293
+ assert (dict_isempty(dict));
294
+ xfree(dict);
295
+ }
296
+
297
+ /*
298
+ * Free all the nodes in the dictionary by using the dictionary's
299
+ * installed free routine. The dictionary is emptied.
300
+ */
301
+
302
+ void dict_free_nodes(dict_t *dict)
303
+ {
304
+ dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
305
+ free_nodes(dict, root, nil);
306
+ dict->nodecount = 0;
307
+ dict->nilnode.left = &dict->nilnode;
308
+ dict->nilnode.right = &dict->nilnode;
309
+ dict->nilnode.parent = &dict->nilnode;
310
+ }
311
+
312
+ /*
313
+ * Obsolescent function, equivalent to dict_free_nodes
314
+ */
315
+
316
+ void dict_free(dict_t *dict)
317
+ {
318
+ #ifdef KAZLIB_OBSOLESCENT_DEBUG
319
+ assert ("call to obsolescent function dict_free()" && 0);
320
+ #endif
321
+ dict_free_nodes(dict);
322
+ }
323
+
324
+ /*
325
+ * Initialize a user-supplied dictionary object.
326
+ */
327
+
328
+ dict_t *dict_init(dict_t *dict, dict_comp_t comp)
329
+ {
330
+ dict->compare = comp;
331
+ dict->allocnode = dnode_alloc;
332
+ dict->freenode = dnode_free;
333
+ dict->context = NULL;
334
+ dict->nodecount = 0;
335
+ dict->nilnode.left = &dict->nilnode;
336
+ dict->nilnode.right = &dict->nilnode;
337
+ dict->nilnode.parent = &dict->nilnode;
338
+ dict->nilnode.color = dnode_black;
339
+ dict->dupes = 0;
340
+ return dict;
341
+ }
342
+
343
+ /*
344
+ * Initialize a dictionary in the likeness of another dictionary
345
+ */
346
+
347
+ void dict_init_like(dict_t *dict, const dict_t *template)
348
+ {
349
+ dict->compare = template->compare;
350
+ dict->allocnode = template->allocnode;
351
+ dict->freenode = template->freenode;
352
+ dict->context = template->context;
353
+ dict->nodecount = 0;
354
+ dict->nilnode.left = &dict->nilnode;
355
+ dict->nilnode.right = &dict->nilnode;
356
+ dict->nilnode.parent = &dict->nilnode;
357
+ dict->nilnode.color = dnode_black;
358
+ dict->dupes = template->dupes;
359
+
360
+ assert (dict_similar(dict, template));
361
+ }
362
+
363
+ /*
364
+ * Remove all nodes from the dictionary (without freeing them in any way).
365
+ */
366
+
367
+ static void dict_clear(dict_t *dict)
368
+ {
369
+ dict->nodecount = 0;
370
+ dict->nilnode.left = &dict->nilnode;
371
+ dict->nilnode.right = &dict->nilnode;
372
+ dict->nilnode.parent = &dict->nilnode;
373
+ assert (dict->nilnode.color == dnode_black);
374
+ }
375
+
376
+ /*
377
+ * Verify the integrity of the dictionary structure. This is provided for
378
+ * debugging purposes, and should be placed in assert statements. Just because
379
+ * this function succeeds doesn't mean that the tree is not corrupt. Certain
380
+ * corruptions in the tree may simply cause undefined behavior.
381
+ */
382
+
383
+ int dict_verify(dict_t *dict)
384
+ {
385
+ dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
386
+
387
+ /* check that the sentinel node and root node are black */
388
+ if (root->color != dnode_black)
389
+ return 0;
390
+ if (nil->color != dnode_black)
391
+ return 0;
392
+ if (nil->right != nil)
393
+ return 0;
394
+ /* nil->left is the root node; check that its parent pointer is nil */
395
+ if (nil->left->parent != nil)
396
+ return 0;
397
+ /* perform a weak test that the tree is a binary search tree */
398
+ if (!verify_bintree(dict))
399
+ return 0;
400
+ /* verify that the tree is a red-black tree */
401
+ if (!verify_redblack(nil, root))
402
+ return 0;
403
+ if (verify_node_count(nil, root) != dict_count(dict))
404
+ return 0;
405
+ return 1;
406
+ }
407
+
408
+ /*
409
+ * Determine whether two dictionaries are similar: have the same comparison and
410
+ * allocator functions, and same status as to whether duplicates are allowed.
411
+ */
412
+
413
+ int dict_similar(const dict_t *left, const dict_t *right)
414
+ {
415
+ if (left->compare != right->compare)
416
+ return 0;
417
+
418
+ if (left->allocnode != right->allocnode)
419
+ return 0;
420
+
421
+ if (left->freenode != right->freenode)
422
+ return 0;
423
+
424
+ if (left->context != right->context)
425
+ return 0;
426
+
427
+ /* if (left->dupes != right->dupes) */
428
+ /* return 0; */
429
+
430
+ return 1;
431
+ }
432
+
433
+ /*
434
+ * Locate a node in the dictionary having the given key.
435
+ * If the node is not found, a null a pointer is returned (rather than
436
+ * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
437
+ * located node is returned.
438
+ */
439
+
440
+ dnode_t *dict_lookup(dict_t *dict, const void *key)
441
+ {
442
+ dnode_t *root = dict_root(dict);
443
+ dnode_t *nil = dict_nil(dict);
444
+ dnode_t *saved;
445
+ int result;
446
+
447
+ /* simple binary search adapted for trees that contain duplicate keys */
448
+
449
+ while (root != nil) {
450
+ result = COMPARE(dict, key, root->key);
451
+ if (result < 0)
452
+ root = root->left;
453
+ else if (result > 0)
454
+ root = root->right;
455
+ else {
456
+ if (!dict->dupes) { /* no duplicates, return match */
457
+ return root;
458
+ } else { /* could be dupes, find leftmost one */
459
+ do {
460
+ saved = root;
461
+ root = root->left;
462
+ while (root != nil && COMPARE(dict, key, root->key))
463
+ root = root->right;
464
+ } while (root != nil);
465
+ return saved;
466
+ }
467
+ }
468
+ }
469
+
470
+ return NULL;
471
+ }
472
+
473
+ /*
474
+ * Look for the node corresponding to the lowest key that is equal to or
475
+ * greater than the given key. If there is no such node, return null.
476
+ */
477
+
478
+ dnode_t *dict_lower_bound(dict_t *dict, const void *key)
479
+ {
480
+ dnode_t *root = dict_root(dict);
481
+ dnode_t *nil = dict_nil(dict);
482
+ dnode_t *tentative = 0;
483
+
484
+ while (root != nil) {
485
+ int result = COMPARE(dict, key, root->key);
486
+
487
+ if (result > 0) {
488
+ root = root->right;
489
+ } else if (result < 0) {
490
+ tentative = root;
491
+ root = root->left;
492
+ } else {
493
+ if (!dict->dupes) {
494
+ return root;
495
+ } else {
496
+ tentative = root;
497
+ root = root->left;
498
+ }
499
+ }
500
+ }
501
+
502
+ return tentative;
503
+ }
504
+
505
+ /*
506
+ * Look for the node corresponding to the greatest key that is equal to or
507
+ * lower than the given key. If there is no such node, return null.
508
+ */
509
+
510
+ dnode_t *dict_upper_bound(dict_t *dict, const void *key)
511
+ {
512
+ dnode_t *root = dict_root(dict);
513
+ dnode_t *nil = dict_nil(dict);
514
+ dnode_t *tentative = 0;
515
+
516
+ while (root != nil) {
517
+ int result = COMPARE(dict, key, root->key);
518
+
519
+ if (result < 0) {
520
+ root = root->left;
521
+ } else if (result > 0) {
522
+ tentative = root;
523
+ root = root->right;
524
+ } else {
525
+ if (!dict->dupes) {
526
+ return root;
527
+ } else {
528
+ tentative = root;
529
+ root = root->right;
530
+ }
531
+ }
532
+ }
533
+
534
+ return tentative;
535
+ }
536
+
537
+ /*
538
+ * Insert a node into the dictionary. The node should have been
539
+ * initialized with a data field. All other fields are ignored.
540
+ * The behavior is undefined if the user attempts to insert into
541
+ * a dictionary that is already full (for which the dict_isfull()
542
+ * function returns true).
543
+ */
544
+
545
+ int dict_insert(dict_t *dict, dnode_t *node, const void *key)
546
+ {
547
+ dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
548
+ dnode_t *parent = nil, *uncle, *grandpa;
549
+ int result = -1;
550
+
551
+ node->key = key;
552
+
553
+ assert (!dict_isfull(dict));
554
+ assert (!dict_contains(dict, node));
555
+ assert (!dnode_is_in_a_dict(node));
556
+
557
+ /* basic binary tree insert */
558
+
559
+ while (where != nil) {
560
+ parent = where;
561
+ result = COMPARE(dict, key, where->key);
562
+ /* trap attempts at duplicate key insertion unless it's explicitly allowed */
563
+
564
+ if (!dict->dupes && result == 0) {
565
+ where->data = node->data;
566
+ return 0;
567
+ } else if (result < 0) {
568
+ where = where->left;
569
+ } else {
570
+ where = where->right;
571
+ }
572
+ }
573
+
574
+ assert (where == nil);
575
+
576
+ if (result < 0)
577
+ parent->left = node;
578
+ else
579
+ parent->right = node;
580
+
581
+ node->parent = parent;
582
+ node->left = nil;
583
+ node->right = nil;
584
+
585
+ dict->nodecount++;
586
+
587
+ /* red black adjustments */
588
+
589
+ node->color = dnode_red;
590
+
591
+ while (parent->color == dnode_red) {
592
+ grandpa = parent->parent;
593
+ if (parent == grandpa->left) {
594
+ uncle = grandpa->right;
595
+ if (uncle->color == dnode_red) { /* red parent, red uncle */
596
+ parent->color = dnode_black;
597
+ uncle->color = dnode_black;
598
+ grandpa->color = dnode_red;
599
+ node = grandpa;
600
+ parent = grandpa->parent;
601
+ } else { /* red parent, black uncle */
602
+ if (node == parent->right) {
603
+ rotate_left(parent);
604
+ parent = node;
605
+ assert (grandpa == parent->parent);
606
+ /* rotation between parent and child preserves grandpa */
607
+ }
608
+ parent->color = dnode_black;
609
+ grandpa->color = dnode_red;
610
+ rotate_right(grandpa);
611
+ break;
612
+ }
613
+ } else { /* symmetric cases: parent == parent->parent->right */
614
+ uncle = grandpa->left;
615
+ if (uncle->color == dnode_red) {
616
+ parent->color = dnode_black;
617
+ uncle->color = dnode_black;
618
+ grandpa->color = dnode_red;
619
+ node = grandpa;
620
+ parent = grandpa->parent;
621
+ } else {
622
+ if (node == parent->left) {
623
+ rotate_right(parent);
624
+ parent = node;
625
+ assert (grandpa == parent->parent);
626
+ }
627
+ parent->color = dnode_black;
628
+ grandpa->color = dnode_red;
629
+ rotate_left(grandpa);
630
+ break;
631
+ }
632
+ }
633
+ }
634
+
635
+ dict_root(dict)->color = dnode_black;
636
+
637
+ assert (dict_verify(dict));
638
+ return 1;
639
+ }
640
+
641
+ /*
642
+ * Delete the given node from the dictionary. If the given node does not belong
643
+ * to the given dictionary, undefined behavior results. A pointer to the
644
+ * deleted node is returned.
645
+ */
646
+
647
+ dnode_t *dict_delete(dict_t *dict, dnode_t *delete)
648
+ {
649
+ dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent;
650
+
651
+ /* basic deletion */
652
+
653
+ assert (!dict_isempty(dict));
654
+ assert (dict_contains(dict, delete));
655
+
656
+ /*
657
+ * If the node being deleted has two children, then we replace it with its
658
+ * successor (i.e. the leftmost node in the right subtree.) By doing this,
659
+ * we avoid the traditional algorithm under which the successor's key and
660
+ * value *only* move to the deleted node and the successor is spliced out
661
+ * from the tree. We cannot use this approach because the user may hold
662
+ * pointers to the successor, or nodes may be inextricably tied to some
663
+ * other structures by way of embedding, etc. So we must splice out the
664
+ * node we are given, not some other node, and must not move contents from
665
+ * one node to another behind the user's back.
666
+ */
667
+
668
+ if (delete->left != nil && delete->right != nil) {
669
+ dnode_t *next = dict_next(dict, delete);
670
+ dnode_t *nextparent = next->parent;
671
+ dnode_color_t nextcolor = next->color;
672
+
673
+ assert (next != nil);
674
+ assert (next->parent != nil);
675
+ assert (next->left == nil);
676
+
677
+ /*
678
+ * First, splice out the successor from the tree completely, by
679
+ * moving up its right child into its place.
680
+ */
681
+
682
+ child = next->right;
683
+ child->parent = nextparent;
684
+
685
+ if (nextparent->left == next) {
686
+ nextparent->left = child;
687
+ } else {
688
+ assert (nextparent->right == next);
689
+ nextparent->right = child;
690
+ }
691
+
692
+ /*
693
+ * Now that the successor has been extricated from the tree, install it
694
+ * in place of the node that we want deleted.
695
+ */
696
+
697
+ next->parent = delparent;
698
+ next->left = delete->left;
699
+ next->right = delete->right;
700
+ next->left->parent = next;
701
+ next->right->parent = next;
702
+ next->color = delete->color;
703
+ delete->color = nextcolor;
704
+
705
+ if (delparent->left == delete) {
706
+ delparent->left = next;
707
+ } else {
708
+ assert (delparent->right == delete);
709
+ delparent->right = next;
710
+ }
711
+
712
+ } else {
713
+ assert (delete != nil);
714
+ assert (delete->left == nil || delete->right == nil);
715
+
716
+ child = (delete->left != nil) ? delete->left : delete->right;
717
+
718
+ child->parent = delparent = delete->parent;
719
+
720
+ if (delete == delparent->left) {
721
+ delparent->left = child;
722
+ } else {
723
+ assert (delete == delparent->right);
724
+ delparent->right = child;
725
+ }
726
+ }
727
+
728
+ delete->parent = NULL;
729
+ delete->right = NULL;
730
+ delete->left = NULL;
731
+
732
+ dict->nodecount--;
733
+
734
+ assert (verify_bintree(dict));
735
+
736
+ /* red-black adjustments */
737
+
738
+ if (delete->color == dnode_black) {
739
+ dnode_t *parent, *sister;
740
+
741
+ dict_root(dict)->color = dnode_red;
742
+
743
+ while (child->color == dnode_black) {
744
+ parent = child->parent;
745
+ if (child == parent->left) {
746
+ sister = parent->right;
747
+ assert (sister != nil);
748
+ if (sister->color == dnode_red) {
749
+ sister->color = dnode_black;
750
+ parent->color = dnode_red;
751
+ rotate_left(parent);
752
+ sister = parent->right;
753
+ assert (sister != nil);
754
+ }
755
+ if (sister->left->color == dnode_black
756
+ && sister->right->color == dnode_black) {
757
+ sister->color = dnode_red;
758
+ child = parent;
759
+ } else {
760
+ if (sister->right->color == dnode_black) {
761
+ assert (sister->left->color == dnode_red);
762
+ sister->left->color = dnode_black;
763
+ sister->color = dnode_red;
764
+ rotate_right(sister);
765
+ sister = parent->right;
766
+ assert (sister != nil);
767
+ }
768
+ sister->color = parent->color;
769
+ sister->right->color = dnode_black;
770
+ parent->color = dnode_black;
771
+ rotate_left(parent);
772
+ break;
773
+ }
774
+ } else { /* symmetric case: child == child->parent->right */
775
+ assert (child == parent->right);
776
+ sister = parent->left;
777
+ assert (sister != nil);
778
+ if (sister->color == dnode_red) {
779
+ sister->color = dnode_black;
780
+ parent->color = dnode_red;
781
+ rotate_right(parent);
782
+ sister = parent->left;
783
+ assert (sister != nil);
784
+ }
785
+ if (sister->right->color == dnode_black
786
+ && sister->left->color == dnode_black) {
787
+ sister->color = dnode_red;
788
+ child = parent;
789
+ } else {
790
+ if (sister->left->color == dnode_black) {
791
+ assert (sister->right->color == dnode_red);
792
+ sister->right->color = dnode_black;
793
+ sister->color = dnode_red;
794
+ rotate_left(sister);
795
+ sister = parent->left;
796
+ assert (sister != nil);
797
+ }
798
+ sister->color = parent->color;
799
+ sister->left->color = dnode_black;
800
+ parent->color = dnode_black;
801
+ rotate_right(parent);
802
+ break;
803
+ }
804
+ }
805
+ }
806
+
807
+ child->color = dnode_black;
808
+ dict_root(dict)->color = dnode_black;
809
+ }
810
+
811
+ assert (dict_verify(dict));
812
+
813
+ return delete;
814
+ }
815
+
816
+ /*
817
+ * Allocate a node using the dictionary's allocator routine, give it
818
+ * the data item.
819
+ */
820
+
821
+ int dict_alloc_insert(dict_t *dict, const void *key, void *data)
822
+ {
823
+ dnode_t *node = dict->allocnode(dict->context);
824
+
825
+ if (node) {
826
+ dnode_init(node, data);
827
+ if (!dict_insert(dict, node, key))
828
+ dict->freenode(node, dict->context);
829
+ return 1;
830
+ }
831
+ return 0;
832
+ }
833
+
834
+ void dict_delete_free(dict_t *dict, dnode_t *node)
835
+ {
836
+ dict_delete(dict, node);
837
+ dict->freenode(node, dict->context);
838
+ }
839
+
840
+ /*
841
+ * Return the node with the lowest (leftmost) key. If the dictionary is empty
842
+ * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
843
+ */
844
+
845
+ dnode_t *dict_first(dict_t *dict)
846
+ {
847
+ dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
848
+
849
+ if (root != nil)
850
+ while ((left = root->left) != nil)
851
+ root = left;
852
+
853
+ return (root == nil) ? NULL : root;
854
+ }
855
+
856
+ /*
857
+ * Return the node with the highest (rightmost) key. If the dictionary is empty
858
+ * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
859
+ */
860
+
861
+ dnode_t *dict_last(dict_t *dict)
862
+ {
863
+ dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right;
864
+
865
+ if (root != nil)
866
+ while ((right = root->right) != nil)
867
+ root = right;
868
+
869
+ return (root == nil) ? NULL : root;
870
+ }
871
+
872
+ /*
873
+ * Return the given node's successor node---the node which has the
874
+ * next key in the the left to right ordering. If the node has
875
+ * no successor, a null pointer is returned rather than a pointer to
876
+ * the nil node.
877
+ */
878
+
879
+ dnode_t *dict_next(dict_t *dict, dnode_t *curr)
880
+ {
881
+ dnode_t *nil = dict_nil(dict), *parent, *left;
882
+
883
+ if (curr->right != nil) {
884
+ curr = curr->right;
885
+ while ((left = curr->left) != nil)
886
+ curr = left;
887
+ return curr;
888
+ }
889
+
890
+ parent = curr->parent;
891
+
892
+ while (parent != nil && curr == parent->right) {
893
+ curr = parent;
894
+ parent = curr->parent;
895
+ }
896
+
897
+ return (parent == nil) ? NULL : parent;
898
+ }
899
+
900
+ /*
901
+ * Return the given node's predecessor, in the key order.
902
+ * The nil sentinel node is returned if there is no predecessor.
903
+ */
904
+
905
+ dnode_t *dict_prev(dict_t *dict, dnode_t *curr)
906
+ {
907
+ dnode_t *nil = dict_nil(dict), *parent, *right;
908
+
909
+ if (curr->left != nil) {
910
+ curr = curr->left;
911
+ while ((right = curr->right) != nil)
912
+ curr = right;
913
+ return curr;
914
+ }
915
+
916
+ parent = curr->parent;
917
+
918
+ while (parent != nil && curr == parent->left) {
919
+ curr = parent;
920
+ parent = curr->parent;
921
+ }
922
+
923
+ return (parent == nil) ? NULL : parent;
924
+ }
925
+
926
+ void dict_allow_dupes(dict_t *dict)
927
+ {
928
+ dict->dupes = 1;
929
+ }
930
+
931
+ dictcount_t dict_count(dict_t *dict)
932
+ {
933
+ return dict->nodecount;
934
+ }
935
+
936
+ int dict_isempty(dict_t *dict)
937
+ {
938
+ return dict->nodecount == 0;
939
+ }
940
+
941
+ int dict_isfull(dict_t *dict)
942
+ {
943
+ return dict->nodecount == DICTCOUNT_T_MAX;
944
+ }
945
+
946
+ int dict_contains(dict_t *dict, dnode_t *node)
947
+ {
948
+ return verify_dict_has_node(dict_nil(dict), dict_root(dict), node);
949
+ }
950
+
951
+ static dnode_t *dnode_alloc(void *context)
952
+ {
953
+ return malloc(sizeof *dnode_alloc(NULL));
954
+ }
955
+
956
+ static void dnode_free(dnode_t *node, void *context)
957
+ {
958
+ free(node);
959
+ }
960
+
961
+ dnode_t *dnode_create(void *data)
962
+ {
963
+ dnode_t *new = malloc(sizeof *new);
964
+ if (new) {
965
+ new->data = data;
966
+ new->parent = NULL;
967
+ new->left = NULL;
968
+ new->right = NULL;
969
+ }
970
+ return new;
971
+ }
972
+
973
+ dnode_t *dnode_init(dnode_t *dnode, void *data)
974
+ {
975
+ dnode->data = data;
976
+ dnode->parent = NULL;
977
+ dnode->left = NULL;
978
+ dnode->right = NULL;
979
+ return dnode;
980
+ }
981
+
982
+ void dnode_destroy(dnode_t *dnode)
983
+ {
984
+ assert (!dnode_is_in_a_dict(dnode));
985
+ free(dnode);
986
+ }
987
+
988
+ void *dnode_get(dnode_t *dnode)
989
+ {
990
+ return dnode->data;
991
+ }
992
+
993
+ const void *dnode_getkey(dnode_t *dnode)
994
+ {
995
+ return dnode->key;
996
+ }
997
+
998
+ void dnode_put(dnode_t *dnode, void *data)
999
+ {
1000
+ dnode->data = data;
1001
+ }
1002
+
1003
+ int dnode_is_in_a_dict(dnode_t *dnode)
1004
+ {
1005
+ return (dnode->parent && dnode->left && dnode->right);
1006
+ }
1007
+
1008
+ void dict_process(dict_t *dict, void *context, dnode_process_t function)
1009
+ {
1010
+ dnode_t *node = dict_first(dict), *next;
1011
+
1012
+ while (node != NULL) {
1013
+ /* check for callback function deleting */
1014
+ /* the next node from under us */
1015
+ assert (dict_contains(dict, node));
1016
+ next = dict_next(dict, node);
1017
+ function(dict, node, context);
1018
+ node = next;
1019
+ }
1020
+ }
1021
+
1022
+ static void load_begin_internal(dict_load_t *load, dict_t *dict)
1023
+ {
1024
+ load->dictptr = dict;
1025
+ load->nilnode.left = &load->nilnode;
1026
+ load->nilnode.right = &load->nilnode;
1027
+ }
1028
+
1029
+ void dict_load_begin(dict_load_t *load, dict_t *dict)
1030
+ {
1031
+ assert (dict_isempty(dict));
1032
+ load_begin_internal(load, dict);
1033
+ }
1034
+
1035
+ void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key)
1036
+ {
1037
+ dict_t *dict = load->dictptr;
1038
+ dnode_t *nil = &load->nilnode;
1039
+
1040
+ assert (!dnode_is_in_a_dict(newnode));
1041
+ assert (dict->nodecount < DICTCOUNT_T_MAX);
1042
+
1043
+ #ifndef NDEBUG
1044
+ if (dict->nodecount > 0) {
1045
+ if (dict->dupes)
1046
+ assert (COMPARE(dict, nil->left->key, key) <= 0);
1047
+ else
1048
+ assert (COMPARE(dict, nil->left->key, key) < 0);
1049
+ }
1050
+ #endif
1051
+
1052
+ newnode->key = key;
1053
+ nil->right->left = newnode;
1054
+ nil->right = newnode;
1055
+ newnode->left = nil;
1056
+ dict->nodecount++;
1057
+ }
1058
+
1059
+ void dict_load_end(dict_load_t *load)
1060
+ {
1061
+ dict_t *dict = load->dictptr;
1062
+ dnode_t *tree[DICT_DEPTH_MAX] = { 0 };
1063
+ dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next;
1064
+ dnode_t *complete = 0;
1065
+ dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount;
1066
+ dictcount_t botrowcount;
1067
+ unsigned baselevel = 0, level = 0, i;
1068
+
1069
+ assert (dnode_red == 0 && dnode_black == 1);
1070
+
1071
+ while (fullcount >= nodecount && fullcount)
1072
+ fullcount >>= 1;
1073
+
1074
+ botrowcount = nodecount - fullcount;
1075
+
1076
+ for (curr = loadnil->left; curr != loadnil; curr = next) {
1077
+ next = curr->left;
1078
+
1079
+ if (complete == NULL && botrowcount-- == 0) {
1080
+ assert (baselevel == 0);
1081
+ assert (level == 0);
1082
+ baselevel = level = 1;
1083
+ complete = tree[0];
1084
+
1085
+ if (complete != 0) {
1086
+ tree[0] = 0;
1087
+ complete->right = dictnil;
1088
+ while (tree[level] != 0) {
1089
+ tree[level]->right = complete;
1090
+ complete->parent = tree[level];
1091
+ complete = tree[level];
1092
+ tree[level++] = 0;
1093
+ }
1094
+ }
1095
+ }
1096
+
1097
+ if (complete == NULL) {
1098
+ curr->left = dictnil;
1099
+ curr->right = dictnil;
1100
+ curr->color = level % 2;
1101
+ complete = curr;
1102
+
1103
+ assert (level == baselevel);
1104
+ while (tree[level] != 0) {
1105
+ tree[level]->right = complete;
1106
+ complete->parent = tree[level];
1107
+ complete = tree[level];
1108
+ tree[level++] = 0;
1109
+ }
1110
+ } else {
1111
+ curr->left = complete;
1112
+ curr->color = (level + 1) % 2;
1113
+ complete->parent = curr;
1114
+ tree[level] = curr;
1115
+ complete = 0;
1116
+ level = baselevel;
1117
+ }
1118
+ }
1119
+
1120
+ if (complete == NULL)
1121
+ complete = dictnil;
1122
+
1123
+ for (i = 0; i < DICT_DEPTH_MAX; i++) {
1124
+ if (tree[i] != 0) {
1125
+ tree[i]->right = complete;
1126
+ complete->parent = tree[i];
1127
+ complete = tree[i];
1128
+ }
1129
+ }
1130
+
1131
+ dictnil->color = dnode_black;
1132
+ dictnil->right = dictnil;
1133
+ complete->parent = dictnil;
1134
+ complete->color = dnode_black;
1135
+ dict_root(dict) = complete;
1136
+
1137
+ assert (dict_verify(dict));
1138
+ }
1139
+
1140
+ void dict_merge(dict_t *dest, dict_t *source)
1141
+ {
1142
+ dict_load_t load;
1143
+ dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source);
1144
+
1145
+ assert (dict_similar(dest, source));
1146
+
1147
+ if (source == dest)
1148
+ return;
1149
+
1150
+ dest->nodecount = 0;
1151
+ load_begin_internal(&load, dest);
1152
+
1153
+ for (;;) {
1154
+ if (leftnode != NULL && rightnode != NULL) {
1155
+ if (COMPARE(dest, leftnode->key, rightnode->key) < 0)
1156
+ goto copyleft;
1157
+ else
1158
+ goto copyright;
1159
+ } else if (leftnode != NULL) {
1160
+ goto copyleft;
1161
+ } else if (rightnode != NULL) {
1162
+ goto copyright;
1163
+ } else {
1164
+ assert (leftnode == NULL && rightnode == NULL);
1165
+ break;
1166
+ }
1167
+
1168
+ copyleft:
1169
+ {
1170
+ dnode_t *next = dict_next(dest, leftnode);
1171
+ #ifndef NDEBUG
1172
+ leftnode->left = NULL; /* suppress assertion in dict_load_next */
1173
+ #endif
1174
+ dict_load_next(&load, leftnode, leftnode->key);
1175
+ leftnode = next;
1176
+ continue;
1177
+ }
1178
+
1179
+ copyright:
1180
+ {
1181
+ dnode_t *next = dict_next(source, rightnode);
1182
+ #ifndef NDEBUG
1183
+ rightnode->left = NULL;
1184
+ #endif
1185
+ dict_load_next(&load, rightnode, rightnode->key);
1186
+ rightnode = next;
1187
+ continue;
1188
+ }
1189
+ }
1190
+
1191
+ dict_clear(source);
1192
+ dict_load_end(&load);
1193
+ }
1194
+
1195
+ int dict_equal(dict_t* dict1, dict_t* dict2,
1196
+ dict_value_eql_t value_eql)
1197
+ {
1198
+ dnode_t* node1;
1199
+ dnode_t* node2;
1200
+
1201
+ if (dict_count(dict1) != dict_count(dict2))
1202
+ return 0;
1203
+ if (!dict_similar(dict1, dict2))
1204
+ return 0;
1205
+
1206
+ for (node1 = dict_first(dict1), node2 = dict_first(dict2);
1207
+ node1 != NULL && node2 != NULL;
1208
+ node1 = dict_next(dict1, node1), node2 = dict_next(dict2, node2)) {
1209
+
1210
+ if (COMPARE(dict1, node1->key, node2->key) != 0)
1211
+ return 0;
1212
+ if (!value_eql(node1->data, node2->data))
1213
+ return 0;
1214
+ }
1215
+ return 1;
1216
+ }