algorithms 0.3.0-jruby
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +172 -0
- data/Manifest +43 -0
- data/README.markdown +93 -0
- data/Rakefile +31 -0
- data/algorithms.gemspec +33 -0
- data/benchmarks/deque.rb +17 -0
- data/benchmarks/sorts.rb +34 -0
- data/benchmarks/treemaps.rb +51 -0
- data/ext/containers/deque/deque.c +247 -0
- data/ext/containers/deque/extconf.rb +4 -0
- data/ext/containers/rbtree_map/extconf.rb +4 -0
- data/ext/containers/rbtree_map/rbtree.c +498 -0
- data/ext/containers/splaytree_map/extconf.rb +4 -0
- data/ext/containers/splaytree_map/splaytree.c +419 -0
- data/lib/algorithms.rb +68 -0
- data/lib/algorithms/search.rb +84 -0
- data/lib/algorithms/sort.rb +238 -0
- data/lib/containers/deque.rb +171 -0
- data/lib/containers/heap.rb +486 -0
- data/lib/containers/kd_tree.rb +110 -0
- data/lib/containers/priority_queue.rb +113 -0
- data/lib/containers/queue.rb +68 -0
- data/lib/containers/rb_tree_map.rb +398 -0
- data/lib/containers/splay_tree_map.rb +269 -0
- data/lib/containers/stack.rb +67 -0
- data/lib/containers/suffix_array.rb +68 -0
- data/lib/containers/trie.rb +182 -0
- data/spec/deque_gc_mark_spec.rb +18 -0
- data/spec/deque_spec.rb +108 -0
- data/spec/heap_spec.rb +126 -0
- data/spec/kd_expected_out.txt +10000 -0
- data/spec/kd_test_in.txt +10000 -0
- data/spec/kd_tree_spec.rb +34 -0
- data/spec/map_gc_mark_spec.rb +27 -0
- data/spec/priority_queue_spec.rb +75 -0
- data/spec/queue_spec.rb +61 -0
- data/spec/rb_tree_map_spec.rb +123 -0
- data/spec/search_spec.rb +28 -0
- data/spec/sort_spec.rb +28 -0
- data/spec/splay_tree_map_spec.rb +106 -0
- data/spec/stack_spec.rb +60 -0
- data/spec/suffix_array_spec.rb +40 -0
- data/spec/trie_spec.rb +59 -0
- 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,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
|
+
}
|