stakach-algorithms 1.0.6 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/README.markdown +99 -97
  2. data/Rakefile +15 -27
  3. data/ext/algorithms/string/extconf.rb +4 -4
  4. data/ext/algorithms/string/string.c +68 -70
  5. data/ext/containers/bst/bst.c +249 -249
  6. data/ext/containers/bst/extconf.rb +4 -4
  7. data/ext/containers/deque/deque.c +248 -248
  8. data/ext/containers/deque/extconf.rb +4 -4
  9. data/ext/containers/rbtree_map/extconf.rb +4 -4
  10. data/ext/containers/rbtree_map/rbtree.c +500 -500
  11. data/ext/containers/splaytree_map/extconf.rb +4 -4
  12. data/ext/containers/splaytree_map/splaytree.c +421 -421
  13. data/lib/algorithms.rb +69 -69
  14. data/lib/algorithms/search.rb +85 -85
  15. data/lib/algorithms/sort.rb +242 -242
  16. data/lib/algorithms/string.rb +10 -10
  17. data/lib/algorithms/version.rb +3 -3
  18. data/lib/containers/deque.rb +176 -176
  19. data/lib/containers/heap.rb +501 -506
  20. data/lib/containers/kd_tree.rb +112 -112
  21. data/lib/containers/priority_queue.rb +116 -116
  22. data/lib/containers/queue.rb +71 -71
  23. data/lib/containers/rb_tree_map.rb +402 -402
  24. data/lib/containers/splay_tree_map.rb +273 -273
  25. data/lib/containers/stack.rb +70 -70
  26. data/lib/containers/suffix_array.rb +71 -71
  27. data/lib/containers/trie.rb +187 -187
  28. data/spec/bst_gc_mark_spec.rb +25 -0
  29. data/spec/bst_spec.rb +25 -0
  30. data/spec/deque_gc_mark_spec.rb +17 -0
  31. data/spec/deque_spec.rb +107 -0
  32. data/spec/heap_spec.rb +130 -0
  33. data/spec/helper.rb +4 -0
  34. data/spec/kd_expected_out.txt +10000 -0
  35. data/spec/kd_test_in.txt +10000 -0
  36. data/spec/kd_tree_spec.rb +33 -0
  37. data/spec/map_gc_mark_spec.rb +28 -0
  38. data/spec/priority_queue_spec.rb +74 -0
  39. data/spec/queue_spec.rb +60 -0
  40. data/spec/rb_tree_map_spec.rb +122 -0
  41. data/spec/search_spec.rb +27 -0
  42. data/spec/sort_spec.rb +26 -0
  43. data/spec/splay_tree_map_spec.rb +105 -0
  44. data/spec/stack_spec.rb +59 -0
  45. data/spec/string_spec.rb +12 -0
  46. data/spec/suffix_array_spec.rb +39 -0
  47. data/spec/trie_spec.rb +58 -0
  48. metadata +60 -4
@@ -1,4 +1,4 @@
1
- require 'mkmf'
2
- extension_name = "CDeque"
3
- dir_config(extension_name)
4
- create_makefile(extension_name)
1
+ require 'mkmf'
2
+ extension_name = "CDeque"
3
+ dir_config(extension_name)
4
+ create_makefile(extension_name)
@@ -1,4 +1,4 @@
1
- require 'mkmf'
2
- extension_name = "CRBTreeMap"
3
- dir_config(extension_name)
4
- create_makefile(extension_name)
1
+ require 'mkmf'
2
+ extension_name = "CRBTreeMap"
3
+ dir_config(extension_name)
4
+ create_makefile(extension_name)
@@ -1,500 +1,500 @@
1
- #include "ruby.h"
2
-
3
- #define RED 1
4
- #define BLACK 0
5
-
6
- #define FALSE 0
7
- #define TRUE 1
8
-
9
- typedef struct struct_rbtree_node {
10
- int color;
11
- VALUE key;
12
- VALUE value;
13
- struct struct_rbtree_node *left;
14
- struct struct_rbtree_node *right;
15
- unsigned int height;
16
- unsigned int num_nodes;
17
- } rbtree_node;
18
-
19
- typedef struct {
20
- unsigned int black_height;
21
- int (*compare_function)(VALUE key1, VALUE key2);
22
- rbtree_node *root;
23
- } rbtree;
24
-
25
- typedef struct struct_ll_node {
26
- rbtree_node *node;
27
- struct struct_ll_node *next;
28
- } ll_node;
29
-
30
- static void recursively_free_nodes(rbtree_node *node) {
31
- if(node) {
32
- recursively_free_nodes(node->left);
33
- recursively_free_nodes(node->right);
34
- free(node);
35
- }
36
- return;
37
- }
38
-
39
- static rbtree* get_tree_from_self(VALUE self) {
40
- rbtree *tree;
41
- Data_Get_Struct(self, rbtree, tree);
42
- return tree;
43
- }
44
-
45
- static int isred(rbtree_node *node) {
46
- if(!node) { return FALSE; }
47
-
48
- if(node->color == RED) { return TRUE; }
49
- else return FALSE;
50
- }
51
-
52
- static void colorflip(rbtree_node *node) {
53
- node->color = !node->color;
54
- node->left->color = !node->left->color;
55
- node->right->color = !node->right->color;
56
- }
57
-
58
- static int size(rbtree_node *h) {
59
- if(!h) {
60
- return 0;
61
- }
62
- else return h->num_nodes;
63
- }
64
-
65
- static int height(rbtree_node *h) {
66
- if(!h) { return 0; }
67
- else return h->height;
68
- }
69
-
70
- static rbtree_node* set_num_nodes(rbtree_node *h) {
71
- h->num_nodes = size(h->left) + size(h->right) + 1;
72
- if ( height(h->left) > height(h->right) ) {
73
- h->height = height(h->left) +1;
74
- }
75
- else {
76
- h->height = height(h->right) +1;
77
- }
78
- return h;
79
- }
80
-
81
- static rbtree_node* rotate_left(rbtree_node *h) {
82
- rbtree_node *x = h->right;
83
- h->right = x->left;
84
- x->left = set_num_nodes(h);
85
- x->color = x->left->color;
86
- x->left->color = RED;
87
- return set_num_nodes(x);
88
- }
89
-
90
- static rbtree_node* rotate_right(rbtree_node *h) {
91
- rbtree_node *x = h->left;
92
- h->left = x->right;
93
- x->right = set_num_nodes(h);
94
- x->color = x->right->color;
95
- x->right->color = RED;
96
- return set_num_nodes(x);
97
- }
98
-
99
- static rbtree_node* move_red_left(rbtree_node *h) {
100
- colorflip(h);
101
- if ( isred(h->right->left) ) {
102
- h->right = rotate_right(h->right);
103
- h = rotate_left(h);
104
- colorflip(h);
105
- }
106
- return h;
107
- }
108
-
109
- static rbtree_node* move_red_right(rbtree_node *h) {
110
- colorflip(h);
111
- if ( isred(h->left->left) ) {
112
- h = rotate_right(h);
113
- colorflip(h);
114
- }
115
- return h;
116
- }
117
-
118
- static rbtree_node* fixup(rbtree_node *h) {
119
- if ( isred(h->right) )
120
- h = rotate_left(h);
121
-
122
- if ( isred(h->left) && isred(h->left->left) )
123
- h = rotate_right(h);
124
-
125
- if ( isred(h->left) && isred(h->right) )
126
- colorflip(h);
127
-
128
- return set_num_nodes(h);
129
- }
130
-
131
- static rbtree* create_rbtree(int (*compare_function)(VALUE, VALUE)) {
132
- rbtree *tree = ALLOC(rbtree);
133
- tree->black_height = 0;
134
- tree->compare_function = compare_function;
135
- tree->root = NULL;
136
- return tree;
137
- }
138
-
139
- static rbtree_node* insert(rbtree *tree, rbtree_node *node, VALUE key, VALUE value) {
140
- int cmp;
141
-
142
- // This slot is empty, so we insert our new node
143
- if(!node) {
144
- rbtree_node *new_node = ALLOC(rbtree_node);
145
- new_node->key = key;
146
- new_node->value = value;
147
- new_node->color = RED;
148
- new_node->height = 1;
149
- new_node->num_nodes = 1;
150
- new_node->left = NULL;
151
- new_node->right = NULL;
152
- return new_node;
153
- }
154
-
155
- // Insert left or right, recursively
156
- cmp = tree->compare_function(key, node->key);
157
- if (cmp == 0) { node->value = value; }
158
- else if (cmp == -1) { node->left = insert(tree, node->left, key, value); }
159
- else { node->right = insert(tree, node->right, key, value); }
160
-
161
- // Fix our tree to keep left-lean
162
- if (isred(node->right)) { node = rotate_left(node); }
163
- if (isred(node->left) && isred(node->left->left)) { node = rotate_right(node); }
164
- if ( isred(node->left) && isred(node->right) ) {
165
- colorflip(node);
166
- }
167
- return set_num_nodes(node);
168
- }
169
-
170
- static VALUE get(rbtree *tree, rbtree_node *node, VALUE key) {
171
- int cmp;
172
- if (!node) {
173
- return Qnil;
174
- }
175
-
176
- cmp = tree->compare_function(key, node->key);
177
- if (cmp == 0) { return node->value; }
178
- else if (cmp == -1) { return get(tree, node->left, key); }
179
- else { return get(tree, node->right, key); }
180
-
181
- }
182
-
183
- static VALUE min_key(rbtree_node *node) {
184
- while (node->left)
185
- node = node->left;
186
-
187
- return node->key;
188
- }
189
-
190
- static VALUE max_key(rbtree_node *node) {
191
- while (node->right)
192
- node = node->right;
193
-
194
- return node->key;
195
- }
196
-
197
- static rbtree_node* delete_min(rbtree_node *h, VALUE *deleted_value) {
198
- if ( !h->left ) {
199
- if(deleted_value)
200
- *deleted_value = h->value;
201
- free(h);
202
- return NULL;
203
- }
204
-
205
- if ( !isred(h->left) && !isred(h->left->left) )
206
- h = move_red_left(h);
207
-
208
- h->left = delete_min(h->left, deleted_value);
209
-
210
- return fixup(h);
211
- }
212
-
213
- static rbtree_node* delete_max(rbtree_node *h, VALUE *deleted_value) {
214
- if ( isred(h->left) )
215
- h = rotate_right(h);
216
-
217
- if ( !h->right ) {
218
- *deleted_value = h->value;
219
- free(h);
220
- return NULL;
221
- }
222
-
223
- if ( !isred(h->right) && !isred(h->right->left) )
224
- h = move_red_right(h);
225
-
226
- h->right = delete_max(h->right, deleted_value);
227
-
228
- return fixup(h);
229
- }
230
-
231
- static rbtree_node* delete(rbtree *tree, rbtree_node *node, VALUE key, VALUE *deleted_value) {
232
- int cmp;
233
- VALUE minimum_key;
234
- cmp = tree->compare_function(key, node->key);
235
- if (cmp == -1) {
236
- if ( !isred(node->left) && !isred(node->left->left) )
237
- node = move_red_left(node);
238
-
239
- node->left = delete(tree, node->left, key, deleted_value);
240
- }
241
- else {
242
- if ( isred(node->left) )
243
- node = rotate_right(node);
244
-
245
- cmp = tree->compare_function(key, node->key);
246
- if ( (cmp == 0) && !node->right ) {
247
- *deleted_value = node->value;
248
- free(node);
249
- return NULL;
250
- }
251
-
252
- if ( !isred(node->right) && !isred(node->right->left) )
253
- node = move_red_right(node);
254
-
255
- cmp = tree->compare_function(key, node->key);
256
- if (cmp == 0) {
257
- *deleted_value = node->value;
258
- minimum_key = min_key(node->right);
259
- node->value = get(tree, node->right, minimum_key);
260
- node->key = minimum_key;
261
- node->right = delete_min(node->right, NULL);
262
- }
263
- else {
264
- node->right = delete(tree, node->right, key, deleted_value);
265
- }
266
- }
267
- return fixup(node);
268
- }
269
-
270
- static rbtree* rbtree_each_node(rbtree *tree, rbtree_node *node, void (*each)(rbtree *tree_, rbtree_node *node_, void* args), void* arguments) {
271
- if (!node)
272
- return NULL;
273
-
274
- if (node->left)
275
- rbtree_each_node(tree, node->left, each, arguments);
276
- (*each)(tree, node, arguments);
277
- if (node->right)
278
- rbtree_each_node(tree, node->right, each, arguments);
279
- return tree;
280
- }
281
-
282
- static rbtree* rbt_each(rbtree *tree, void (*each)(rbtree *tree, rbtree_node *node, void *args), void* arguments) {
283
- if (tree->root)
284
- rbtree_each_node(tree, tree->root, each, arguments);
285
- return tree;
286
- }
287
-
288
- // Methods to be called in Ruby
289
-
290
- static int id_compare_operator;
291
-
292
- static int rbtree_compare_function(VALUE a, VALUE b) {
293
- if (a == b) return 0;
294
- if (FIXNUM_P(a) && FIXNUM_P(b)) {
295
- long x = FIX2LONG(a), y = FIX2LONG(b);
296
- if (x == y) return 0;
297
- if (x > y) return 1;
298
- return -1;
299
- }
300
- if (TYPE(a) == T_STRING && rb_obj_is_kind_of(a, rb_cString) &&
301
- TYPE(b) == T_STRING && rb_obj_is_kind_of(b, rb_cString)) {
302
- return rb_str_cmp(a, b);
303
- }
304
- return FIX2INT(rb_funcall((VALUE) a, id_compare_operator, 1, (VALUE) b));
305
- }
306
-
307
- static VALUE rbtree_init(VALUE self)
308
- {
309
- return self;
310
- }
311
-
312
- static void rbtree_mark(void *ptr) {
313
- ll_node *current, *new, *last, *old;
314
- if (ptr) {
315
- rbtree *tree = ptr;
316
-
317
- if (tree->root) {
318
- current = ALLOC(ll_node);
319
- last = current;
320
- current->node = tree->root;
321
- current->next = NULL;
322
-
323
- while(current) {
324
- rb_gc_mark(current->node->key);
325
- rb_gc_mark(current->node->value);
326
- if (current->node->left) {
327
- new = ALLOC(ll_node);
328
- new->node = current->node->left;
329
- new->next = NULL;
330
- last->next = new;
331
- last = new;
332
- }
333
- if (current->node->right) {
334
- new = ALLOC(ll_node);
335
- new->node = current->node->right;
336
- new->next = NULL;
337
- last->next = new;
338
- last = new;
339
- }
340
- old = current;
341
- current = current->next;
342
- free(old);
343
- }
344
- }
345
- }
346
- }
347
-
348
- static void rbtree_free(void *ptr) {
349
- if (ptr) {
350
- rbtree *tree = ptr;
351
- recursively_free_nodes(tree->root);
352
- free(tree);
353
- }
354
- }
355
-
356
- static VALUE rbtree_alloc(VALUE klass) {
357
- rbtree *tree = create_rbtree(&rbtree_compare_function);
358
- return Data_Wrap_Struct(klass, rbtree_mark, rbtree_free, tree);
359
- }
360
-
361
- static VALUE rbtree_push(VALUE self, VALUE key, VALUE value) {
362
- rbtree *tree = get_tree_from_self(self);
363
- tree->root = insert(tree, tree->root, key, value);
364
- return value;
365
- }
366
-
367
- static VALUE rbtree_get(VALUE self, VALUE key) {
368
- rbtree *tree = get_tree_from_self(self);
369
- return get(tree, tree->root, key);
370
- }
371
-
372
- static VALUE rbtree_size(VALUE self) {
373
- rbtree *tree = get_tree_from_self(self);
374
- return INT2NUM(size(tree->root));
375
- }
376
-
377
- static VALUE rbtree_is_empty(VALUE self) {
378
- rbtree *tree = get_tree_from_self(self);
379
- return (tree->root ? Qfalse : Qtrue);
380
- }
381
-
382
- static VALUE rbtree_height(VALUE self) {
383
- rbtree *tree = get_tree_from_self(self);
384
- return INT2NUM(height(tree->root));
385
- }
386
-
387
- static VALUE rbtree_has_key(VALUE self, VALUE key) {
388
- rbtree *tree = get_tree_from_self(self);
389
- if(!tree->root) { return Qfalse; }
390
- if(get(tree, tree->root, key) == Qnil)
391
- return Qfalse;
392
-
393
- return Qtrue;
394
- }
395
-
396
- static VALUE rbtree_min_key(VALUE self) {
397
- rbtree *tree = get_tree_from_self(self);
398
- if(!tree->root)
399
- return Qnil;
400
-
401
- return min_key(tree->root);
402
- }
403
-
404
- static VALUE rbtree_max_key(VALUE self) {
405
- rbtree *tree = get_tree_from_self(self);
406
- if(!tree->root)
407
- return Qnil;
408
-
409
- return max_key(tree->root);
410
- }
411
-
412
- static VALUE rbtree_delete(VALUE self, VALUE key) {
413
- VALUE deleted_value;
414
- rbtree *tree = get_tree_from_self(self);
415
- if(!tree->root)
416
- return Qnil;
417
-
418
- tree->root = delete(tree, tree->root, key, &deleted_value);
419
- if(tree->root)
420
- tree->root->color = BLACK;
421
-
422
- if(deleted_value) {
423
- return deleted_value;
424
- }
425
-
426
- return Qnil;
427
- }
428
-
429
- static VALUE rbtree_delete_min(VALUE self) {
430
- VALUE deleted_value;
431
- rbtree *tree = get_tree_from_self(self);
432
- if(!tree->root)
433
- return Qnil;
434
-
435
- tree->root = delete_min(tree->root, &deleted_value);
436
- if(tree->root)
437
- tree->root->color = BLACK;
438
-
439
- if(deleted_value) {
440
- return deleted_value;
441
- }
442
-
443
- return Qnil;
444
- }
445
-
446
- static VALUE rbtree_delete_max(VALUE self) {
447
- VALUE deleted_value;
448
- rbtree *tree = get_tree_from_self(self);
449
- if(!tree->root)
450
- return Qnil;
451
-
452
- tree->root = delete_max(tree->root, &deleted_value);
453
- if(tree->root)
454
- tree->root->color = BLACK;
455
-
456
- if(deleted_value) {
457
- return deleted_value;
458
- }
459
-
460
- return Qnil;
461
- }
462
-
463
- static void rbtree_each_helper(rbtree *tree, rbtree_node *node, void *args) {
464
- rb_yield(rb_ary_new3(2, node->key, node->value));
465
- };
466
-
467
- static VALUE rbtree_each(VALUE self) {
468
- rbtree *tree = get_tree_from_self(self);
469
- rbt_each(tree, &rbtree_each_helper, NULL);
470
- return self;
471
- }
472
-
473
- static VALUE cRBTree;
474
- static VALUE mContainers;
475
- static VALUE namespace;
476
-
477
- void Init_CRBTreeMap() {
478
- id_compare_operator = rb_intern("<=>");
479
-
480
- namespace = rb_define_module("Algorithms");
481
- mContainers = rb_define_module_under(namespace,"Containers");
482
- cRBTree = rb_define_class_under(mContainers, "CRBTreeMap", rb_cObject);
483
- rb_define_alloc_func(cRBTree, rbtree_alloc);
484
- rb_define_method(cRBTree, "initialize", rbtree_init, 0);
485
- rb_define_method(cRBTree, "push", rbtree_push, 2);
486
- rb_define_alias(cRBTree, "[]=", "push");
487
- rb_define_method(cRBTree, "size", rbtree_size, 0);
488
- rb_define_method(cRBTree, "empty?", rbtree_is_empty, 0);
489
- rb_define_method(cRBTree, "height", rbtree_height, 0);
490
- rb_define_method(cRBTree, "min_key", rbtree_min_key, 0);
491
- rb_define_method(cRBTree, "max_key", rbtree_max_key, 0);
492
- rb_define_method(cRBTree, "delete_min", rbtree_delete_min, 0);
493
- rb_define_method(cRBTree, "delete_max", rbtree_delete_max, 0);
494
- rb_define_method(cRBTree, "each", rbtree_each, 0);
495
- rb_define_method(cRBTree, "get", rbtree_get, 1);
496
- rb_define_alias(cRBTree, "[]", "get");
497
- rb_define_method(cRBTree, "has_key?", rbtree_has_key, 1);
498
- rb_define_method(cRBTree, "delete", rbtree_delete, 1);
499
- rb_include_module(cRBTree, rb_eval_string("Enumerable"));
500
- }
1
+ #include "ruby.h"
2
+
3
+ #define RED 1
4
+ #define BLACK 0
5
+
6
+ #define FALSE 0
7
+ #define TRUE 1
8
+
9
+ typedef struct struct_rbtree_node {
10
+ int color;
11
+ VALUE key;
12
+ VALUE value;
13
+ struct struct_rbtree_node *left;
14
+ struct struct_rbtree_node *right;
15
+ unsigned int height;
16
+ unsigned int num_nodes;
17
+ } rbtree_node;
18
+
19
+ typedef struct {
20
+ unsigned int black_height;
21
+ int (*compare_function)(VALUE key1, VALUE key2);
22
+ rbtree_node *root;
23
+ } rbtree;
24
+
25
+ typedef struct struct_ll_node {
26
+ rbtree_node *node;
27
+ struct struct_ll_node *next;
28
+ } ll_node;
29
+
30
+ static void recursively_free_nodes(rbtree_node *node) {
31
+ if(node) {
32
+ recursively_free_nodes(node->left);
33
+ recursively_free_nodes(node->right);
34
+ free(node);
35
+ }
36
+ return;
37
+ }
38
+
39
+ static rbtree* get_tree_from_self(VALUE self) {
40
+ rbtree *tree;
41
+ Data_Get_Struct(self, rbtree, tree);
42
+ return tree;
43
+ }
44
+
45
+ static int isred(rbtree_node *node) {
46
+ if(!node) { return FALSE; }
47
+
48
+ if(node->color == RED) { return TRUE; }
49
+ else return FALSE;
50
+ }
51
+
52
+ static void colorflip(rbtree_node *node) {
53
+ node->color = !node->color;
54
+ node->left->color = !node->left->color;
55
+ node->right->color = !node->right->color;
56
+ }
57
+
58
+ static int size(rbtree_node *h) {
59
+ if(!h) {
60
+ return 0;
61
+ }
62
+ else return h->num_nodes;
63
+ }
64
+
65
+ static int height(rbtree_node *h) {
66
+ if(!h) { return 0; }
67
+ else return h->height;
68
+ }
69
+
70
+ static rbtree_node* set_num_nodes(rbtree_node *h) {
71
+ h->num_nodes = size(h->left) + size(h->right) + 1;
72
+ if ( height(h->left) > height(h->right) ) {
73
+ h->height = height(h->left) +1;
74
+ }
75
+ else {
76
+ h->height = height(h->right) +1;
77
+ }
78
+ return h;
79
+ }
80
+
81
+ static rbtree_node* rotate_left(rbtree_node *h) {
82
+ rbtree_node *x = h->right;
83
+ h->right = x->left;
84
+ x->left = set_num_nodes(h);
85
+ x->color = x->left->color;
86
+ x->left->color = RED;
87
+ return set_num_nodes(x);
88
+ }
89
+
90
+ static rbtree_node* rotate_right(rbtree_node *h) {
91
+ rbtree_node *x = h->left;
92
+ h->left = x->right;
93
+ x->right = set_num_nodes(h);
94
+ x->color = x->right->color;
95
+ x->right->color = RED;
96
+ return set_num_nodes(x);
97
+ }
98
+
99
+ static rbtree_node* move_red_left(rbtree_node *h) {
100
+ colorflip(h);
101
+ if ( isred(h->right->left) ) {
102
+ h->right = rotate_right(h->right);
103
+ h = rotate_left(h);
104
+ colorflip(h);
105
+ }
106
+ return h;
107
+ }
108
+
109
+ static rbtree_node* move_red_right(rbtree_node *h) {
110
+ colorflip(h);
111
+ if ( isred(h->left->left) ) {
112
+ h = rotate_right(h);
113
+ colorflip(h);
114
+ }
115
+ return h;
116
+ }
117
+
118
+ static rbtree_node* fixup(rbtree_node *h) {
119
+ if ( isred(h->right) )
120
+ h = rotate_left(h);
121
+
122
+ if ( isred(h->left) && isred(h->left->left) )
123
+ h = rotate_right(h);
124
+
125
+ if ( isred(h->left) && isred(h->right) )
126
+ colorflip(h);
127
+
128
+ return set_num_nodes(h);
129
+ }
130
+
131
+ static rbtree* create_rbtree(int (*compare_function)(VALUE, VALUE)) {
132
+ rbtree *tree = ALLOC(rbtree);
133
+ tree->black_height = 0;
134
+ tree->compare_function = compare_function;
135
+ tree->root = NULL;
136
+ return tree;
137
+ }
138
+
139
+ static rbtree_node* insert(rbtree *tree, rbtree_node *node, VALUE key, VALUE value) {
140
+ int cmp;
141
+
142
+ // This slot is empty, so we insert our new node
143
+ if(!node) {
144
+ rbtree_node *new_node = ALLOC(rbtree_node);
145
+ new_node->key = key;
146
+ new_node->value = value;
147
+ new_node->color = RED;
148
+ new_node->height = 1;
149
+ new_node->num_nodes = 1;
150
+ new_node->left = NULL;
151
+ new_node->right = NULL;
152
+ return new_node;
153
+ }
154
+
155
+ // Insert left or right, recursively
156
+ cmp = tree->compare_function(key, node->key);
157
+ if (cmp == 0) { node->value = value; }
158
+ else if (cmp == -1) { node->left = insert(tree, node->left, key, value); }
159
+ else { node->right = insert(tree, node->right, key, value); }
160
+
161
+ // Fix our tree to keep left-lean
162
+ if (isred(node->right)) { node = rotate_left(node); }
163
+ if (isred(node->left) && isred(node->left->left)) { node = rotate_right(node); }
164
+ if ( isred(node->left) && isred(node->right) ) {
165
+ colorflip(node);
166
+ }
167
+ return set_num_nodes(node);
168
+ }
169
+
170
+ static VALUE get(rbtree *tree, rbtree_node *node, VALUE key) {
171
+ int cmp;
172
+ if (!node) {
173
+ return Qnil;
174
+ }
175
+
176
+ cmp = tree->compare_function(key, node->key);
177
+ if (cmp == 0) { return node->value; }
178
+ else if (cmp == -1) { return get(tree, node->left, key); }
179
+ else { return get(tree, node->right, key); }
180
+
181
+ }
182
+
183
+ static VALUE min_key(rbtree_node *node) {
184
+ while (node->left)
185
+ node = node->left;
186
+
187
+ return node->key;
188
+ }
189
+
190
+ static VALUE max_key(rbtree_node *node) {
191
+ while (node->right)
192
+ node = node->right;
193
+
194
+ return node->key;
195
+ }
196
+
197
+ static rbtree_node* delete_min(rbtree_node *h, VALUE *deleted_value) {
198
+ if ( !h->left ) {
199
+ if(deleted_value)
200
+ *deleted_value = h->value;
201
+ free(h);
202
+ return NULL;
203
+ }
204
+
205
+ if ( !isred(h->left) && !isred(h->left->left) )
206
+ h = move_red_left(h);
207
+
208
+ h->left = delete_min(h->left, deleted_value);
209
+
210
+ return fixup(h);
211
+ }
212
+
213
+ static rbtree_node* delete_max(rbtree_node *h, VALUE *deleted_value) {
214
+ if ( isred(h->left) )
215
+ h = rotate_right(h);
216
+
217
+ if ( !h->right ) {
218
+ *deleted_value = h->value;
219
+ free(h);
220
+ return NULL;
221
+ }
222
+
223
+ if ( !isred(h->right) && !isred(h->right->left) )
224
+ h = move_red_right(h);
225
+
226
+ h->right = delete_max(h->right, deleted_value);
227
+
228
+ return fixup(h);
229
+ }
230
+
231
+ static rbtree_node* delete(rbtree *tree, rbtree_node *node, VALUE key, VALUE *deleted_value) {
232
+ int cmp;
233
+ VALUE minimum_key;
234
+ cmp = tree->compare_function(key, node->key);
235
+ if (cmp == -1) {
236
+ if ( !isred(node->left) && !isred(node->left->left) )
237
+ node = move_red_left(node);
238
+
239
+ node->left = delete(tree, node->left, key, deleted_value);
240
+ }
241
+ else {
242
+ if ( isred(node->left) )
243
+ node = rotate_right(node);
244
+
245
+ cmp = tree->compare_function(key, node->key);
246
+ if ( (cmp == 0) && !node->right ) {
247
+ *deleted_value = node->value;
248
+ free(node);
249
+ return NULL;
250
+ }
251
+
252
+ if ( !isred(node->right) && !isred(node->right->left) )
253
+ node = move_red_right(node);
254
+
255
+ cmp = tree->compare_function(key, node->key);
256
+ if (cmp == 0) {
257
+ *deleted_value = node->value;
258
+ minimum_key = min_key(node->right);
259
+ node->value = get(tree, node->right, minimum_key);
260
+ node->key = minimum_key;
261
+ node->right = delete_min(node->right, NULL);
262
+ }
263
+ else {
264
+ node->right = delete(tree, node->right, key, deleted_value);
265
+ }
266
+ }
267
+ return fixup(node);
268
+ }
269
+
270
+ static rbtree* rbtree_each_node(rbtree *tree, rbtree_node *node, void (*each)(rbtree *tree_, rbtree_node *node_, void* args), void* arguments) {
271
+ if (!node)
272
+ return NULL;
273
+
274
+ if (node->left)
275
+ rbtree_each_node(tree, node->left, each, arguments);
276
+ (*each)(tree, node, arguments);
277
+ if (node->right)
278
+ rbtree_each_node(tree, node->right, each, arguments);
279
+ return tree;
280
+ }
281
+
282
+ static rbtree* rbt_each(rbtree *tree, void (*each)(rbtree *tree, rbtree_node *node, void *args), void* arguments) {
283
+ if (tree->root)
284
+ rbtree_each_node(tree, tree->root, each, arguments);
285
+ return tree;
286
+ }
287
+
288
+ // Methods to be called in Ruby
289
+
290
+ static VALUE id_compare_operator;
291
+
292
+ static int rbtree_compare_function(VALUE a, VALUE b) {
293
+ if (a == b) return 0;
294
+ if (FIXNUM_P(a) && FIXNUM_P(b)) {
295
+ long x = FIX2LONG(a), y = FIX2LONG(b);
296
+ if (x == y) return 0;
297
+ if (x > y) return 1;
298
+ return -1;
299
+ }
300
+ if (TYPE(a) == T_STRING && rb_obj_is_kind_of(a, rb_cString) &&
301
+ TYPE(b) == T_STRING && rb_obj_is_kind_of(b, rb_cString)) {
302
+ return rb_str_cmp(a, b);
303
+ }
304
+ return FIX2INT(rb_funcall((VALUE) a, id_compare_operator, 1, (VALUE) b));
305
+ }
306
+
307
+ static VALUE rbtree_init(VALUE self)
308
+ {
309
+ return self;
310
+ }
311
+
312
+ static void rbtree_mark(void *ptr) {
313
+ ll_node *current, *new, *last, *old;
314
+ if (ptr) {
315
+ rbtree *tree = ptr;
316
+
317
+ if (tree->root) {
318
+ current = ALLOC(ll_node);
319
+ last = current;
320
+ current->node = tree->root;
321
+ current->next = NULL;
322
+
323
+ while(current) {
324
+ rb_gc_mark(current->node->key);
325
+ rb_gc_mark(current->node->value);
326
+ if (current->node->left) {
327
+ new = ALLOC(ll_node);
328
+ new->node = current->node->left;
329
+ new->next = NULL;
330
+ last->next = new;
331
+ last = new;
332
+ }
333
+ if (current->node->right) {
334
+ new = ALLOC(ll_node);
335
+ new->node = current->node->right;
336
+ new->next = NULL;
337
+ last->next = new;
338
+ last = new;
339
+ }
340
+ old = current;
341
+ current = current->next;
342
+ free(old);
343
+ }
344
+ }
345
+ }
346
+ }
347
+
348
+ static void rbtree_free(void *ptr) {
349
+ if (ptr) {
350
+ rbtree *tree = ptr;
351
+ recursively_free_nodes(tree->root);
352
+ free(tree);
353
+ }
354
+ }
355
+
356
+ static VALUE rbtree_alloc(VALUE klass) {
357
+ rbtree *tree = create_rbtree(&rbtree_compare_function);
358
+ return Data_Wrap_Struct(klass, rbtree_mark, rbtree_free, tree);
359
+ }
360
+
361
+ static VALUE rbtree_push(VALUE self, VALUE key, VALUE value) {
362
+ rbtree *tree = get_tree_from_self(self);
363
+ tree->root = insert(tree, tree->root, key, value);
364
+ return value;
365
+ }
366
+
367
+ static VALUE rbtree_get(VALUE self, VALUE key) {
368
+ rbtree *tree = get_tree_from_self(self);
369
+ return get(tree, tree->root, key);
370
+ }
371
+
372
+ static VALUE rbtree_size(VALUE self) {
373
+ rbtree *tree = get_tree_from_self(self);
374
+ return INT2NUM(size(tree->root));
375
+ }
376
+
377
+ static VALUE rbtree_is_empty(VALUE self) {
378
+ rbtree *tree = get_tree_from_self(self);
379
+ return (tree->root ? Qfalse : Qtrue);
380
+ }
381
+
382
+ static VALUE rbtree_height(VALUE self) {
383
+ rbtree *tree = get_tree_from_self(self);
384
+ return INT2NUM(height(tree->root));
385
+ }
386
+
387
+ static VALUE rbtree_has_key(VALUE self, VALUE key) {
388
+ rbtree *tree = get_tree_from_self(self);
389
+ if(!tree->root) { return Qfalse; }
390
+ if(get(tree, tree->root, key) == Qnil)
391
+ return Qfalse;
392
+
393
+ return Qtrue;
394
+ }
395
+
396
+ static VALUE rbtree_min_key(VALUE self) {
397
+ rbtree *tree = get_tree_from_self(self);
398
+ if(!tree->root)
399
+ return Qnil;
400
+
401
+ return min_key(tree->root);
402
+ }
403
+
404
+ static VALUE rbtree_max_key(VALUE self) {
405
+ rbtree *tree = get_tree_from_self(self);
406
+ if(!tree->root)
407
+ return Qnil;
408
+
409
+ return max_key(tree->root);
410
+ }
411
+
412
+ static VALUE rbtree_delete(VALUE self, VALUE key) {
413
+ VALUE deleted_value;
414
+ rbtree *tree = get_tree_from_self(self);
415
+ if(!tree->root)
416
+ return Qnil;
417
+
418
+ tree->root = delete(tree, tree->root, key, &deleted_value);
419
+ if(tree->root)
420
+ tree->root->color = BLACK;
421
+
422
+ if(deleted_value) {
423
+ return deleted_value;
424
+ }
425
+
426
+ return Qnil;
427
+ }
428
+
429
+ static VALUE rbtree_delete_min(VALUE self) {
430
+ VALUE deleted_value;
431
+ rbtree *tree = get_tree_from_self(self);
432
+ if(!tree->root)
433
+ return Qnil;
434
+
435
+ tree->root = delete_min(tree->root, &deleted_value);
436
+ if(tree->root)
437
+ tree->root->color = BLACK;
438
+
439
+ if(deleted_value) {
440
+ return deleted_value;
441
+ }
442
+
443
+ return Qnil;
444
+ }
445
+
446
+ static VALUE rbtree_delete_max(VALUE self) {
447
+ VALUE deleted_value;
448
+ rbtree *tree = get_tree_from_self(self);
449
+ if(!tree->root)
450
+ return Qnil;
451
+
452
+ tree->root = delete_max(tree->root, &deleted_value);
453
+ if(tree->root)
454
+ tree->root->color = BLACK;
455
+
456
+ if(deleted_value) {
457
+ return deleted_value;
458
+ }
459
+
460
+ return Qnil;
461
+ }
462
+
463
+ static void rbtree_each_helper(rbtree *tree, rbtree_node *node, void *args) {
464
+ rb_yield(rb_ary_new3(2, node->key, node->value));
465
+ };
466
+
467
+ static VALUE rbtree_each(VALUE self) {
468
+ rbtree *tree = get_tree_from_self(self);
469
+ rbt_each(tree, &rbtree_each_helper, NULL);
470
+ return self;
471
+ }
472
+
473
+ static VALUE cRBTree;
474
+ static VALUE mContainers;
475
+ static VALUE namespace;
476
+
477
+ void Init_CRBTreeMap() {
478
+ id_compare_operator = rb_intern("<=>");
479
+
480
+ namespace = rb_define_module("Algorithms");
481
+ mContainers = rb_define_module_under(namespace,"Containers");
482
+ cRBTree = rb_define_class_under(mContainers, "CRBTreeMap", rb_cObject);
483
+ rb_define_alloc_func(cRBTree, rbtree_alloc);
484
+ rb_define_method(cRBTree, "initialize", rbtree_init, 0);
485
+ rb_define_method(cRBTree, "push", rbtree_push, 2);
486
+ rb_define_alias(cRBTree, "[]=", "push");
487
+ rb_define_method(cRBTree, "size", rbtree_size, 0);
488
+ rb_define_method(cRBTree, "empty?", rbtree_is_empty, 0);
489
+ rb_define_method(cRBTree, "height", rbtree_height, 0);
490
+ rb_define_method(cRBTree, "min_key", rbtree_min_key, 0);
491
+ rb_define_method(cRBTree, "max_key", rbtree_max_key, 0);
492
+ rb_define_method(cRBTree, "delete_min", rbtree_delete_min, 0);
493
+ rb_define_method(cRBTree, "delete_max", rbtree_delete_max, 0);
494
+ rb_define_method(cRBTree, "each", rbtree_each, 0);
495
+ rb_define_method(cRBTree, "get", rbtree_get, 1);
496
+ rb_define_alias(cRBTree, "[]", "get");
497
+ rb_define_method(cRBTree, "has_key?", rbtree_has_key, 1);
498
+ rb_define_method(cRBTree, "delete", rbtree_delete, 1);
499
+ rb_include_module(cRBTree, rb_eval_string("Enumerable"));
500
+ }