kanwei-algorithms 0.2.0

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