algorithms 0.3.0-jruby

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/History.txt +172 -0
  2. data/Manifest +43 -0
  3. data/README.markdown +93 -0
  4. data/Rakefile +31 -0
  5. data/algorithms.gemspec +33 -0
  6. data/benchmarks/deque.rb +17 -0
  7. data/benchmarks/sorts.rb +34 -0
  8. data/benchmarks/treemaps.rb +51 -0
  9. data/ext/containers/deque/deque.c +247 -0
  10. data/ext/containers/deque/extconf.rb +4 -0
  11. data/ext/containers/rbtree_map/extconf.rb +4 -0
  12. data/ext/containers/rbtree_map/rbtree.c +498 -0
  13. data/ext/containers/splaytree_map/extconf.rb +4 -0
  14. data/ext/containers/splaytree_map/splaytree.c +419 -0
  15. data/lib/algorithms.rb +68 -0
  16. data/lib/algorithms/search.rb +84 -0
  17. data/lib/algorithms/sort.rb +238 -0
  18. data/lib/containers/deque.rb +171 -0
  19. data/lib/containers/heap.rb +486 -0
  20. data/lib/containers/kd_tree.rb +110 -0
  21. data/lib/containers/priority_queue.rb +113 -0
  22. data/lib/containers/queue.rb +68 -0
  23. data/lib/containers/rb_tree_map.rb +398 -0
  24. data/lib/containers/splay_tree_map.rb +269 -0
  25. data/lib/containers/stack.rb +67 -0
  26. data/lib/containers/suffix_array.rb +68 -0
  27. data/lib/containers/trie.rb +182 -0
  28. data/spec/deque_gc_mark_spec.rb +18 -0
  29. data/spec/deque_spec.rb +108 -0
  30. data/spec/heap_spec.rb +126 -0
  31. data/spec/kd_expected_out.txt +10000 -0
  32. data/spec/kd_test_in.txt +10000 -0
  33. data/spec/kd_tree_spec.rb +34 -0
  34. data/spec/map_gc_mark_spec.rb +27 -0
  35. data/spec/priority_queue_spec.rb +75 -0
  36. data/spec/queue_spec.rb +61 -0
  37. data/spec/rb_tree_map_spec.rb +123 -0
  38. data/spec/search_spec.rb +28 -0
  39. data/spec/sort_spec.rb +28 -0
  40. data/spec/splay_tree_map_spec.rb +106 -0
  41. data/spec/stack_spec.rb +60 -0
  42. data/spec/suffix_array_spec.rb +40 -0
  43. data/spec/trie_spec.rb +59 -0
  44. metadata +122 -0
@@ -0,0 +1,247 @@
1
+ #include "ruby.h"
2
+
3
+ #define FALSE 0
4
+ #define TRUE 1
5
+
6
+ typedef struct struct_deque_node {
7
+ VALUE obj;
8
+ struct struct_deque_node *left;
9
+ struct struct_deque_node *right;
10
+ } deque_node;
11
+
12
+ typedef struct {
13
+ unsigned int size;
14
+ deque_node *front;
15
+ deque_node *back;
16
+ } deque;
17
+
18
+ void free_nodes(deque_node *node) {
19
+ deque_node *next;
20
+ while(node) {
21
+ next = node->right;
22
+ free(node);
23
+ node = next;
24
+ }
25
+ return;
26
+ }
27
+
28
+ void clear_deque(deque *a_deque) {
29
+ if(a_deque->front)
30
+ free_nodes(a_deque->front);
31
+ a_deque->size = 0;
32
+ a_deque->front = NULL;
33
+ a_deque->back = NULL;
34
+ return;
35
+ }
36
+
37
+ static deque* get_deque_from_self(VALUE self) {
38
+ deque *a_deque;
39
+ Data_Get_Struct(self, deque, a_deque);
40
+ return a_deque;
41
+ }
42
+
43
+ static deque* create_deque() {
44
+ deque *a_deque = ALLOC(deque);
45
+ a_deque->size = 0;
46
+ a_deque->front = NULL;
47
+ a_deque->back = NULL;
48
+ return a_deque;
49
+ }
50
+
51
+ static deque_node* create_node(VALUE obj) {
52
+ deque_node *node = ALLOC(deque_node);
53
+ node->obj = obj;
54
+ node->left = NULL;
55
+ node->right = NULL;
56
+ return node;
57
+ }
58
+
59
+ static void deque_mark(void *ptr) {
60
+ if (ptr) {
61
+ deque *deque = ptr;
62
+ deque_node *node = deque->front;
63
+ while(node) {
64
+ rb_gc_mark(node->obj);
65
+ node = node->right;
66
+ }
67
+ }
68
+ }
69
+
70
+ static void deque_free(void *ptr) {
71
+ if (ptr) {
72
+ deque *deque = ptr;
73
+ free_nodes(deque->front);
74
+ free(deque);
75
+ }
76
+ }
77
+
78
+ static VALUE deque_alloc(VALUE klass) {
79
+ deque *deque = create_deque();
80
+ return Data_Wrap_Struct(klass, deque_mark, deque_free, deque);
81
+ }
82
+
83
+ static VALUE deque_push_front(VALUE self, VALUE obj) {
84
+ deque *deque = get_deque_from_self(self);
85
+ deque_node *node = create_node(obj);
86
+ if(deque->front) {
87
+ node->right = deque->front;
88
+ deque->front->left = node;
89
+ deque->front = node;
90
+ }
91
+ else {
92
+ deque->front = node;
93
+ deque->back = node;
94
+ }
95
+ deque->size++;
96
+ return obj;
97
+ }
98
+
99
+ static VALUE deque_push_back(VALUE self, VALUE obj) {
100
+ deque *deque = get_deque_from_self(self);
101
+ deque_node *node = create_node(obj);
102
+ if(deque->back) {
103
+ node->left = deque->back;
104
+ deque->back->right = node;
105
+ deque->back = node;
106
+ }
107
+ else {
108
+ deque->front = node;
109
+ deque->back = node;
110
+ }
111
+ deque->size++;
112
+ return obj;
113
+ }
114
+
115
+ static VALUE deque_pop_front(VALUE self) {
116
+ deque *deque = get_deque_from_self(self);
117
+ VALUE obj;
118
+ if(!deque->front)
119
+ return Qnil;
120
+ deque_node *node = deque->front;
121
+ obj = node->obj;
122
+ if(deque->size == 1) {
123
+ clear_deque(deque);
124
+ return obj;
125
+ }
126
+ deque->front->right->left = NULL;
127
+ deque->front = deque->front->right;
128
+ deque->size--;
129
+ return obj;
130
+ }
131
+
132
+ static VALUE deque_front(VALUE self) {
133
+ deque *deque = get_deque_from_self(self);
134
+ if(deque->front)
135
+ return deque->front->obj;
136
+
137
+ return Qnil;
138
+ }
139
+
140
+ static VALUE deque_back(VALUE self) {
141
+ deque *deque = get_deque_from_self(self);
142
+ if(deque->back)
143
+ return deque->back->obj;
144
+
145
+ return Qnil;
146
+ }
147
+
148
+ static VALUE deque_pop_back(VALUE self) {
149
+ deque *deque = get_deque_from_self(self);
150
+ VALUE obj;
151
+ if(!deque->back)
152
+ return Qnil;
153
+ deque_node *node = deque->back;
154
+ obj = node->obj;
155
+ if(deque->size == 1) {
156
+ clear_deque(deque);
157
+ return obj;
158
+ }
159
+ deque->back->left->right = NULL;
160
+ deque->back = deque->back->left;
161
+ deque->size--;
162
+ return obj;
163
+ }
164
+
165
+ static VALUE deque_clear(VALUE self) {
166
+ deque *deque = get_deque_from_self(self);
167
+ clear_deque(deque);
168
+ return Qnil;
169
+ }
170
+
171
+ static VALUE deque_size(VALUE self) {
172
+ deque *deque = get_deque_from_self(self);
173
+ return INT2NUM(deque->size);
174
+ }
175
+
176
+ static VALUE deque_is_empty(VALUE self) {
177
+ deque *deque = get_deque_from_self(self);
178
+ return (deque->size == 0) ? Qtrue : Qfalse;
179
+ }
180
+
181
+ static VALUE deque_each_forward(VALUE self) {
182
+ deque *deque = get_deque_from_self(self);
183
+ deque_node *node = deque->front;
184
+ while(node) {
185
+ rb_yield(node->obj);
186
+ node = node->right;
187
+ }
188
+ return self;
189
+ }
190
+
191
+ static VALUE deque_each_backward(VALUE self) {
192
+ deque *deque = get_deque_from_self(self);
193
+ deque_node *node = deque->back;
194
+ while(node) {
195
+ rb_yield(node->obj);
196
+ node = node->left;
197
+ }
198
+ return self;
199
+ }
200
+
201
+ static VALUE deque_init(int argc, VALUE *argv, VALUE self)
202
+ {
203
+ int len, i;
204
+ VALUE ary;
205
+
206
+ if(argc == 0) {
207
+ return self;
208
+ }
209
+ else if(argc > 1) {
210
+ rb_raise(rb_eArgError, "wrong number of arguments");
211
+ }
212
+ else {
213
+ ary = rb_check_array_type(argv[0]);
214
+ if(!NIL_P(ary)) {
215
+ len = RARRAY_LEN(ary);
216
+ for (i = 0; i < len; i++) {
217
+ deque_push_back(self, RARRAY_PTR(ary)[i]);
218
+ }
219
+ }
220
+ }
221
+ return self;
222
+ }
223
+
224
+ static VALUE cDeque;
225
+ static VALUE mContainers;
226
+
227
+ void Init_CDeque() {
228
+ mContainers = rb_define_module("Containers");
229
+ cDeque = rb_define_class_under(mContainers, "CDeque", rb_cObject);
230
+ rb_define_alloc_func(cDeque, deque_alloc);
231
+ rb_define_method(cDeque, "initialize", deque_init, -1);
232
+ rb_define_method(cDeque, "push_front", deque_push_front, 1);
233
+ rb_define_method(cDeque, "push_back", deque_push_back, 1);
234
+ rb_define_method(cDeque, "clear", deque_clear, 0);
235
+ rb_define_method(cDeque, "front", deque_front, 0);
236
+ rb_define_method(cDeque, "back", deque_back, 0);
237
+ rb_define_method(cDeque, "pop_front", deque_pop_front, 0);
238
+ rb_define_method(cDeque, "pop_back", deque_pop_back, 0);
239
+ rb_define_method(cDeque, "size", deque_size, 0);
240
+ rb_define_alias(cDeque, "length", "size");
241
+ rb_define_method(cDeque, "empty?", deque_is_empty, 0);
242
+ rb_define_method(cDeque, "each_forward", deque_each_forward, 0);
243
+ rb_define_method(cDeque, "each_backward", deque_each_backward, 0);
244
+ rb_define_alias(cDeque, "each", "each_forward");
245
+ rb_define_alias(cDeque, "reverse_each", "each_backward");
246
+ rb_include_module(cDeque, rb_eval_string("Enumerable"));
247
+ }
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+ extension_name = "CDeque"
3
+ dir_config(extension_name)
4
+ create_makefile(extension_name)
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+ extension_name = "CRBTreeMap"
3
+ dir_config(extension_name)
4
+ create_makefile(extension_name)
@@ -0,0 +1,498 @@
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
+
476
+ void Init_CRBTreeMap() {
477
+ id_compare_operator = rb_intern("<=>");
478
+
479
+ mContainers = rb_define_module("Containers");
480
+ cRBTree = rb_define_class_under(mContainers, "CRBTreeMap", rb_cObject);
481
+ rb_define_alloc_func(cRBTree, rbtree_alloc);
482
+ rb_define_method(cRBTree, "initialize", rbtree_init, 0);
483
+ rb_define_method(cRBTree, "push", rbtree_push, 2);
484
+ rb_define_alias(cRBTree, "[]=", "push");
485
+ rb_define_method(cRBTree, "size", rbtree_size, 0);
486
+ rb_define_method(cRBTree, "empty?", rbtree_is_empty, 0);
487
+ rb_define_method(cRBTree, "height", rbtree_height, 0);
488
+ rb_define_method(cRBTree, "min_key", rbtree_min_key, 0);
489
+ rb_define_method(cRBTree, "max_key", rbtree_max_key, 0);
490
+ rb_define_method(cRBTree, "delete_min", rbtree_delete_min, 0);
491
+ rb_define_method(cRBTree, "delete_max", rbtree_delete_max, 0);
492
+ rb_define_method(cRBTree, "each", rbtree_each, 0);
493
+ rb_define_method(cRBTree, "get", rbtree_get, 1);
494
+ rb_define_alias(cRBTree, "[]", "get");
495
+ rb_define_method(cRBTree, "has_key?", rbtree_has_key, 1);
496
+ rb_define_method(cRBTree, "delete", rbtree_delete, 1);
497
+ rb_include_module(cRBTree, rb_eval_string("Enumerable"));
498
+ }