algorithms 0.2.0 → 1.0.0
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.
- checksums.yaml +7 -0
- data/{History.txt → CHANGELOG.markdown} +25 -0
- data/Gemfile +9 -0
- data/Manifest +16 -6
- data/README.markdown +40 -66
- data/Rakefile +16 -25
- data/algorithms.gemspec +14 -24
- data/benchmarks/treemaps.rb +25 -10
- data/ext/algorithms/string/extconf.rb +4 -0
- data/ext/algorithms/string/string.c +68 -0
- data/ext/containers/bst/bst.c +247 -0
- data/ext/containers/bst/extconf.rb +4 -0
- data/ext/containers/deque/deque.c +3 -3
- data/ext/containers/rbtree_map/rbtree.c +43 -18
- data/ext/containers/splaytree_map/splaytree.c +154 -105
- data/lib/algorithms.rb +5 -6
- data/lib/algorithms/sort.rb +130 -0
- data/lib/algorithms/string.rb +9 -0
- data/lib/containers/heap.rb +16 -0
- data/lib/containers/kd_tree.rb +40 -17
- data/lib/containers/trie.rb +1 -1
- data/spec/bst_gc_mark_spec.rb +25 -0
- data/spec/bst_spec.rb +25 -0
- data/spec/deque_gc_mark_spec.rb +1 -1
- data/spec/deque_spec.rb +20 -20
- data/spec/heap_spec.rb +28 -23
- data/spec/kd_expected_out.txt +10000 -0
- data/spec/kd_test_in.txt +10000 -0
- data/spec/kd_tree_spec.rb +31 -1
- data/spec/{rb_tree_map_gc_mark_spec.rb → map_gc_mark_spec.rb} +10 -6
- data/spec/priority_queue_spec.rb +20 -20
- data/spec/queue_spec.rb +10 -10
- data/spec/rb_tree_map_spec.rb +25 -25
- data/spec/search_spec.rb +9 -9
- data/spec/sort_spec.rb +6 -5
- data/spec/splay_tree_map_spec.rb +21 -17
- data/spec/stack_spec.rb +10 -10
- data/spec/string_spec.rb +15 -0
- data/spec/suffix_array_spec.rb +17 -17
- data/spec/trie_spec.rb +16 -16
- metadata +49 -62
@@ -0,0 +1,247 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
typedef struct struct_bst_node {
|
4
|
+
VALUE key;
|
5
|
+
VALUE value;
|
6
|
+
struct struct_bst_node *left;
|
7
|
+
struct struct_bst_node *right;
|
8
|
+
struct struct_bst_node *parent;
|
9
|
+
} bst_node;
|
10
|
+
|
11
|
+
typedef struct struct_bst {
|
12
|
+
bst_node *root;
|
13
|
+
int (*compare_function)(VALUE key1, VALUE key2);
|
14
|
+
unsigned int size;
|
15
|
+
} bst;
|
16
|
+
|
17
|
+
static VALUE bst_initialize(VALUE self) {
|
18
|
+
return self;
|
19
|
+
}
|
20
|
+
|
21
|
+
static bst* get_bst_from_self(VALUE self) {
|
22
|
+
bst *tree;
|
23
|
+
Data_Get_Struct(self, bst, tree);
|
24
|
+
return tree;
|
25
|
+
}
|
26
|
+
|
27
|
+
static bst* bst_each_node(bst *tree, bst_node *node, void (*each)(bst *tree_, bst_node *node_, void* args), void* arguments) {
|
28
|
+
if (!node)
|
29
|
+
return NULL;
|
30
|
+
|
31
|
+
if (node->left)
|
32
|
+
bst_each_node(tree, node->left, each, arguments);
|
33
|
+
|
34
|
+
(*each)(tree, node, arguments);
|
35
|
+
|
36
|
+
if (node->right)
|
37
|
+
bst_each_node(tree, node->right, each, arguments);
|
38
|
+
return tree;
|
39
|
+
}
|
40
|
+
|
41
|
+
static bst* bst_each(bst *tree, void (*each)(bst *tree, bst_node *node, void *args), void* arguments) {
|
42
|
+
if (tree->root)
|
43
|
+
bst_each_node(tree, tree->root, each, arguments);
|
44
|
+
return tree;
|
45
|
+
}
|
46
|
+
|
47
|
+
static VALUE id_compare_operator;
|
48
|
+
|
49
|
+
static int bst_compare_function(VALUE a, VALUE b) {
|
50
|
+
if (a == b) return 0;
|
51
|
+
if (FIXNUM_P(a) && FIXNUM_P(b)) {
|
52
|
+
long x = FIX2LONG(a), y = FIX2LONG(b);
|
53
|
+
if (x == y) return 0;
|
54
|
+
if (x > y) return 1;
|
55
|
+
return -1;
|
56
|
+
}
|
57
|
+
if (TYPE(a) == T_STRING && rb_obj_is_kind_of(a, rb_cString) &&
|
58
|
+
TYPE(b) == T_STRING && rb_obj_is_kind_of(b, rb_cString)) {
|
59
|
+
return rb_str_cmp(a, b);
|
60
|
+
}
|
61
|
+
return FIX2INT(rb_funcall((VALUE) a, id_compare_operator, 1, (VALUE) b));
|
62
|
+
}
|
63
|
+
|
64
|
+
static void insert_element(bst *tree, bst_node **t,bst_node *newElement) {
|
65
|
+
int cmp;
|
66
|
+
bst_node *y = NULL;
|
67
|
+
bst_node *x = *t;
|
68
|
+
while (x != NULL) {
|
69
|
+
y = x;
|
70
|
+
cmp = tree->compare_function(newElement->key, x->key);
|
71
|
+
if (cmp < 0) x = x->left;
|
72
|
+
else x = x->right;
|
73
|
+
}
|
74
|
+
newElement->parent = y;
|
75
|
+
if (y == NULL) *t = newElement;
|
76
|
+
else {
|
77
|
+
cmp = tree->compare_function(newElement->key, y->key);
|
78
|
+
if (cmp < 0)
|
79
|
+
y->left = newElement;
|
80
|
+
else
|
81
|
+
y->right = newElement;
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
|
86
|
+
static bst_node* create_node(VALUE key_value,VALUE value) {
|
87
|
+
bst_node *new_node = ALLOC(bst_node);
|
88
|
+
new_node->value = value;
|
89
|
+
new_node->key = key_value;
|
90
|
+
new_node->left = NULL;
|
91
|
+
new_node->right = NULL;
|
92
|
+
new_node->parent = NULL;
|
93
|
+
return new_node;
|
94
|
+
}
|
95
|
+
|
96
|
+
static bst_node* tree_minimum (bst_node *tree) {
|
97
|
+
bst_node *x = tree;
|
98
|
+
while (x->left) x = x->left;
|
99
|
+
return x;
|
100
|
+
}
|
101
|
+
|
102
|
+
static bst_node* tree_maximum (bst_node *tree) {
|
103
|
+
bst_node *x = tree;
|
104
|
+
while (x->right) x = x->right;
|
105
|
+
return x;
|
106
|
+
}
|
107
|
+
|
108
|
+
static bst_node* node_successor (bst_node *tree,bst_node *x) {
|
109
|
+
if (x->right) return tree_minimum(x->right);
|
110
|
+
bst_node *y = x->parent;
|
111
|
+
while (y && x == y->right) {
|
112
|
+
x = y;
|
113
|
+
y = x->parent;
|
114
|
+
}
|
115
|
+
return y;
|
116
|
+
}
|
117
|
+
|
118
|
+
|
119
|
+
static bst_node* delete_node (bst_node **tree,bst_node *tobeDeleted) {
|
120
|
+
bst_node *y,*x;
|
121
|
+
|
122
|
+
if ((tobeDeleted->left == NULL) || (tobeDeleted->right == NULL)) y = tobeDeleted;
|
123
|
+
else y = node_successor(*tree,tobeDeleted);
|
124
|
+
|
125
|
+
if (y->left) x = y->left;
|
126
|
+
else x = y->right;
|
127
|
+
|
128
|
+
if (x) x->parent = y->parent;
|
129
|
+
|
130
|
+
if (y->parent == NULL) {
|
131
|
+
*tree = x;
|
132
|
+
return y;
|
133
|
+
} else if (y == y->parent->left) {
|
134
|
+
y->parent->left = x;
|
135
|
+
} else {
|
136
|
+
y->parent->right = x;
|
137
|
+
}
|
138
|
+
|
139
|
+
if (tobeDeleted != y) tobeDeleted->key = y->key;
|
140
|
+
return y;
|
141
|
+
}
|
142
|
+
|
143
|
+
static bst_node* search_node(bst *tree, bst_node *node, VALUE key) {
|
144
|
+
bst_node *x = node;
|
145
|
+
int cmp;
|
146
|
+
|
147
|
+
while(x) {
|
148
|
+
cmp = tree->compare_function(key, x->key);
|
149
|
+
if (cmp == 0) return x;
|
150
|
+
else if (cmp < 0) { x = x->left; }
|
151
|
+
else { x = x->right; }
|
152
|
+
}
|
153
|
+
return NULL;
|
154
|
+
}
|
155
|
+
|
156
|
+
static void recursively_mark_nodes(bst_node *node) {
|
157
|
+
if(node) {
|
158
|
+
rb_gc_mark(node->key);
|
159
|
+
rb_gc_mark(node->value);
|
160
|
+
recursively_mark_nodes(node->left);
|
161
|
+
recursively_mark_nodes(node->right);
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
static void bst_mark(bst *tree) {
|
166
|
+
if (tree) {
|
167
|
+
recursively_mark_nodes(tree->root);
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
static void recursively_free_nodes(bst_node *node) {
|
172
|
+
if(node) {
|
173
|
+
recursively_free_nodes(node->left);
|
174
|
+
recursively_free_nodes(node->right);
|
175
|
+
xfree(node);
|
176
|
+
}
|
177
|
+
}
|
178
|
+
|
179
|
+
static void bst_free(bst *tree) {
|
180
|
+
if (tree) {
|
181
|
+
recursively_free_nodes(tree->root);
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
185
|
+
static bst* create_bst(int (*compare_function)(VALUE, VALUE)) {
|
186
|
+
bst *tree = ALLOC(bst);
|
187
|
+
tree->compare_function = compare_function;
|
188
|
+
tree->root = NULL;
|
189
|
+
tree->size = 0;
|
190
|
+
return tree;
|
191
|
+
}
|
192
|
+
|
193
|
+
static VALUE bst_alloc(VALUE klass) {
|
194
|
+
bst *tree = create_bst(&bst_compare_function);
|
195
|
+
return Data_Wrap_Struct(klass, bst_mark, bst_free, tree);
|
196
|
+
}
|
197
|
+
|
198
|
+
static VALUE rb_bst_push_value(VALUE self, VALUE key, VALUE value) {
|
199
|
+
bst *tree = get_bst_from_self(self);
|
200
|
+
insert_element(tree, &(tree->root), create_node(key,value));
|
201
|
+
tree->size++;
|
202
|
+
return self;
|
203
|
+
}
|
204
|
+
|
205
|
+
static void bst_each_helper(bst *tree, bst_node *node, void *args) {
|
206
|
+
rb_yield(rb_ary_new3(2, node->key, node->value));
|
207
|
+
};
|
208
|
+
|
209
|
+
static VALUE rb_bst_each(VALUE self) {
|
210
|
+
bst *tree = get_bst_from_self(self);
|
211
|
+
bst_each(tree, &bst_each_helper, NULL);
|
212
|
+
return self;
|
213
|
+
}
|
214
|
+
|
215
|
+
static VALUE rb_bst_delete(VALUE self, VALUE key) {
|
216
|
+
bst *tree = get_bst_from_self(self);
|
217
|
+
bst_node *tobeDeleted = search_node(tree, tree->root, key);
|
218
|
+
if(tobeDeleted) {
|
219
|
+
tree->size -= 1;
|
220
|
+
bst_node *deletedNode = delete_node(&(tree->root),tobeDeleted);
|
221
|
+
return deletedNode->value;
|
222
|
+
}
|
223
|
+
return Qnil;
|
224
|
+
}
|
225
|
+
|
226
|
+
static VALUE rb_bst_size(VALUE self) {
|
227
|
+
bst *tree;
|
228
|
+
Data_Get_Struct(self,bst,tree);
|
229
|
+
return INT2FIX(tree->size);
|
230
|
+
}
|
231
|
+
|
232
|
+
static VALUE CBst;
|
233
|
+
static VALUE mContainers;
|
234
|
+
|
235
|
+
void Init_CBst() {
|
236
|
+
id_compare_operator = rb_intern("<=>");
|
237
|
+
|
238
|
+
mContainers = rb_define_module("Containers");
|
239
|
+
CBst = rb_define_class_under(mContainers, "CBst", rb_cObject);
|
240
|
+
rb_define_alloc_func(CBst, bst_alloc);
|
241
|
+
rb_define_method(CBst, "initialize", bst_initialize, 0);
|
242
|
+
rb_define_method(CBst, "push", rb_bst_push_value, 2);
|
243
|
+
rb_define_alias(CBst, "[]=", "push");
|
244
|
+
rb_define_method(CBst, "each", rb_bst_each, 0);
|
245
|
+
rb_define_method(CBst, "delete", rb_bst_delete, 1);
|
246
|
+
rb_define_method(CBst, "size", rb_bst_size, 0);
|
247
|
+
}
|
@@ -19,7 +19,7 @@ void free_nodes(deque_node *node) {
|
|
19
19
|
deque_node *next;
|
20
20
|
while(node) {
|
21
21
|
next = node->right;
|
22
|
-
|
22
|
+
xfree(node);
|
23
23
|
node = next;
|
24
24
|
}
|
25
25
|
return;
|
@@ -71,7 +71,7 @@ static void deque_free(void *ptr) {
|
|
71
71
|
if (ptr) {
|
72
72
|
deque *deque = ptr;
|
73
73
|
free_nodes(deque->front);
|
74
|
-
|
74
|
+
xfree(deque);
|
75
75
|
}
|
76
76
|
}
|
77
77
|
|
@@ -200,7 +200,7 @@ static VALUE deque_each_backward(VALUE self) {
|
|
200
200
|
|
201
201
|
static VALUE deque_init(int argc, VALUE *argv, VALUE self)
|
202
202
|
{
|
203
|
-
|
203
|
+
long len, i;
|
204
204
|
VALUE ary;
|
205
205
|
|
206
206
|
if(argc == 0) {
|
@@ -22,11 +22,16 @@ typedef struct {
|
|
22
22
|
rbtree_node *root;
|
23
23
|
} rbtree;
|
24
24
|
|
25
|
+
typedef struct struct_ll_node {
|
26
|
+
rbtree_node *node;
|
27
|
+
struct struct_ll_node *next;
|
28
|
+
} ll_node;
|
29
|
+
|
25
30
|
static void recursively_free_nodes(rbtree_node *node) {
|
26
31
|
if(node) {
|
27
32
|
recursively_free_nodes(node->left);
|
28
33
|
recursively_free_nodes(node->right);
|
29
|
-
|
34
|
+
xfree(node);
|
30
35
|
}
|
31
36
|
return;
|
32
37
|
}
|
@@ -193,7 +198,7 @@ static rbtree_node* delete_min(rbtree_node *h, VALUE *deleted_value) {
|
|
193
198
|
if ( !h->left ) {
|
194
199
|
if(deleted_value)
|
195
200
|
*deleted_value = h->value;
|
196
|
-
|
201
|
+
xfree(h);
|
197
202
|
return NULL;
|
198
203
|
}
|
199
204
|
|
@@ -211,7 +216,7 @@ static rbtree_node* delete_max(rbtree_node *h, VALUE *deleted_value) {
|
|
211
216
|
|
212
217
|
if ( !h->right ) {
|
213
218
|
*deleted_value = h->value;
|
214
|
-
|
219
|
+
xfree(h);
|
215
220
|
return NULL;
|
216
221
|
}
|
217
222
|
|
@@ -240,7 +245,7 @@ static rbtree_node* delete(rbtree *tree, rbtree_node *node, VALUE key, VALUE *de
|
|
240
245
|
cmp = tree->compare_function(key, node->key);
|
241
246
|
if ( (cmp == 0) && !node->right ) {
|
242
247
|
*deleted_value = node->value;
|
243
|
-
|
248
|
+
xfree(node);
|
244
249
|
return NULL;
|
245
250
|
}
|
246
251
|
|
@@ -282,7 +287,7 @@ static rbtree* rbt_each(rbtree *tree, void (*each)(rbtree *tree, rbtree_node *no
|
|
282
287
|
|
283
288
|
// Methods to be called in Ruby
|
284
289
|
|
285
|
-
static
|
290
|
+
static VALUE id_compare_operator;
|
286
291
|
|
287
292
|
static int rbtree_compare_function(VALUE a, VALUE b) {
|
288
293
|
if (a == b) return 0;
|
@@ -292,8 +297,8 @@ static int rbtree_compare_function(VALUE a, VALUE b) {
|
|
292
297
|
if (x > y) return 1;
|
293
298
|
return -1;
|
294
299
|
}
|
295
|
-
if (TYPE(a) == T_STRING &&
|
296
|
-
|
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)) {
|
297
302
|
return rb_str_cmp(a, b);
|
298
303
|
}
|
299
304
|
return FIX2INT(rb_funcall((VALUE) a, id_compare_operator, 1, (VALUE) b));
|
@@ -304,19 +309,39 @@ static VALUE rbtree_init(VALUE self)
|
|
304
309
|
return self;
|
305
310
|
}
|
306
311
|
|
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
312
|
static void rbtree_mark(void *ptr) {
|
313
|
+
ll_node *current, *new, *last, *old;
|
317
314
|
if (ptr) {
|
318
315
|
rbtree *tree = ptr;
|
319
|
-
|
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
|
+
xfree(old);
|
343
|
+
}
|
344
|
+
}
|
320
345
|
}
|
321
346
|
}
|
322
347
|
|
@@ -324,7 +349,7 @@ static void rbtree_free(void *ptr) {
|
|
324
349
|
if (ptr) {
|
325
350
|
rbtree *tree = ptr;
|
326
351
|
recursively_free_nodes(tree->root);
|
327
|
-
|
352
|
+
xfree(tree);
|
328
353
|
}
|
329
354
|
}
|
330
355
|
|
@@ -1,24 +1,34 @@
|
|
1
1
|
#include "ruby.h"
|
2
2
|
|
3
|
+
#define node_size(x) (((x)==NULL) ? 0 : ((x)->size))
|
4
|
+
|
5
|
+
/* Using http://www.link.cs.cmu.edu/link/ftp-site/splaying/top-down-size-splay.c as reference,
|
6
|
+
written by D. Sleator <sleator@cs.cmu.edu>, January 1994.
|
7
|
+
*/
|
8
|
+
|
3
9
|
typedef struct struct_splaytree_node {
|
4
10
|
VALUE key;
|
5
11
|
VALUE value;
|
12
|
+
int size;
|
6
13
|
struct struct_splaytree_node *left;
|
7
14
|
struct struct_splaytree_node *right;
|
8
15
|
} splaytree_node;
|
9
16
|
|
10
17
|
typedef struct {
|
11
18
|
int (*compare_function)(VALUE key1, VALUE key2);
|
12
|
-
int size;
|
13
19
|
splaytree_node *root;
|
14
|
-
splaytree_node *header;
|
15
20
|
} splaytree;
|
16
21
|
|
22
|
+
typedef struct struct_ll_node {
|
23
|
+
splaytree_node *node;
|
24
|
+
struct struct_ll_node *next;
|
25
|
+
} ll_node;
|
26
|
+
|
17
27
|
static void recursively_free_nodes(splaytree_node *node) {
|
18
28
|
if(node) {
|
19
29
|
recursively_free_nodes(node->left);
|
20
30
|
recursively_free_nodes(node->right);
|
21
|
-
|
31
|
+
xfree(node);
|
22
32
|
}
|
23
33
|
return;
|
24
34
|
}
|
@@ -29,55 +39,75 @@ static splaytree* get_tree_from_self(VALUE self) {
|
|
29
39
|
return tree;
|
30
40
|
}
|
31
41
|
|
32
|
-
static
|
33
|
-
int cmp, cmp2;
|
34
|
-
splaytree_node
|
42
|
+
static splaytree_node* splay(splaytree *tree, splaytree_node *n, VALUE key) {
|
43
|
+
int cmp, cmp2, root_size, l_size, r_size;
|
44
|
+
splaytree_node N;
|
45
|
+
splaytree_node *l, *r, *y;
|
35
46
|
|
36
|
-
|
37
|
-
r = tree->header;
|
38
|
-
t = tree->root;
|
47
|
+
if (!n) return n;
|
39
48
|
|
40
|
-
|
41
|
-
|
49
|
+
N.left = N.right = NULL;
|
50
|
+
l = r = &N;
|
51
|
+
root_size = node_size(n);
|
52
|
+
l_size = r_size = 0;
|
42
53
|
|
43
54
|
while(1) {
|
44
|
-
cmp = tree->compare_function(key,
|
55
|
+
cmp = tree->compare_function(key, n->key);
|
45
56
|
if (cmp == -1) {
|
46
|
-
if (!
|
47
|
-
cmp2 = tree->compare_function(key,
|
57
|
+
if (!n->left) break;
|
58
|
+
cmp2 = tree->compare_function(key, n->left->key);
|
48
59
|
if (cmp2 == -1) {
|
49
|
-
y =
|
50
|
-
|
51
|
-
y->right =
|
52
|
-
|
53
|
-
|
60
|
+
y = n->left;
|
61
|
+
n->left = y->right;
|
62
|
+
y->right = n;
|
63
|
+
n->size = node_size(n->left) + node_size(n->right) + 1;
|
64
|
+
n = y;
|
65
|
+
if (!n->left) break;
|
54
66
|
}
|
55
|
-
r->left =
|
56
|
-
r =
|
57
|
-
|
58
|
-
|
59
|
-
else if (cmp == 1) {
|
60
|
-
if (!
|
61
|
-
cmp2 = tree->compare_function(key,
|
67
|
+
r->left = n;
|
68
|
+
r = n;
|
69
|
+
n = n->left;
|
70
|
+
r_size += 1 + node_size(r->right);
|
71
|
+
} else if (cmp == 1) {
|
72
|
+
if (!n->right) break;
|
73
|
+
cmp2 = tree->compare_function(key, n->right->key);
|
62
74
|
if (cmp2 == 1) {
|
63
|
-
y =
|
64
|
-
|
65
|
-
y->left =
|
66
|
-
|
67
|
-
|
75
|
+
y = n->right;
|
76
|
+
n->right = y->left;
|
77
|
+
y->left = n;
|
78
|
+
n->size = node_size(n->left) + node_size(n->right) + 1;
|
79
|
+
n = y;
|
80
|
+
if (!n->right) break;
|
68
81
|
}
|
69
|
-
l->right =
|
70
|
-
l =
|
71
|
-
|
82
|
+
l->right = n;
|
83
|
+
l = n;
|
84
|
+
n = n->right;
|
85
|
+
l_size += 1 + node_size(l->left);
|
72
86
|
} else {
|
73
87
|
break;
|
74
88
|
}
|
75
89
|
}
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
90
|
+
|
91
|
+
l_size += node_size(n->left);
|
92
|
+
r_size += node_size(n->right);
|
93
|
+
n->size = l_size + r_size + 1;
|
94
|
+
l->right = r->left = NULL;
|
95
|
+
|
96
|
+
for (y = N.right; y != NULL; y = y->right) {
|
97
|
+
y->size = l_size;
|
98
|
+
l_size -= 1 + node_size(y->left);
|
99
|
+
}
|
100
|
+
for (y = N.left; y != NULL; y = y->left) {
|
101
|
+
y->size = r_size;
|
102
|
+
r_size -= 1 + node_size(y->right);
|
103
|
+
}
|
104
|
+
|
105
|
+
l->right = n->left;
|
106
|
+
r->left = n->right;
|
107
|
+
n->left = N.right;
|
108
|
+
n->right = N.left;
|
109
|
+
|
110
|
+
return n;
|
81
111
|
}
|
82
112
|
|
83
113
|
static int height(splaytree_node *h) {
|
@@ -95,8 +125,6 @@ static splaytree* create_splaytree(int (*compare_function)(VALUE, VALUE)) {
|
|
95
125
|
splaytree *tree = ALLOC(splaytree);
|
96
126
|
tree->compare_function = compare_function;
|
97
127
|
tree->root = NULL;
|
98
|
-
tree->size = 0;
|
99
|
-
tree->header = ALLOC(splaytree_node);
|
100
128
|
return tree;
|
101
129
|
}
|
102
130
|
|
@@ -109,44 +137,46 @@ static splaytree_node* create_node(VALUE key, VALUE value) {
|
|
109
137
|
return new_node;
|
110
138
|
}
|
111
139
|
|
112
|
-
static
|
140
|
+
static splaytree_node* insert(splaytree *tree, splaytree_node *n, VALUE key, VALUE value) {
|
113
141
|
int cmp;
|
114
142
|
splaytree_node *new_node;
|
115
143
|
|
116
|
-
if (
|
117
|
-
|
118
|
-
tree->
|
119
|
-
|
120
|
-
|
144
|
+
if (n) {
|
145
|
+
n = splay(tree, n, key);
|
146
|
+
cmp = tree->compare_function(key, n->key);
|
147
|
+
if (cmp == 0) {
|
148
|
+
n->value = value;
|
149
|
+
return n;
|
150
|
+
}
|
121
151
|
}
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
if (cmp == 0) {
|
126
|
-
tree->root->value = value;
|
127
|
-
return;
|
152
|
+
new_node = create_node(key, value);
|
153
|
+
if (!n) {
|
154
|
+
new_node->left = new_node->right = NULL;
|
128
155
|
} else {
|
129
|
-
|
130
|
-
if (cmp
|
131
|
-
new_node->left =
|
132
|
-
new_node->right =
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
new_node->
|
137
|
-
|
156
|
+
cmp = tree->compare_function(key, n->key);
|
157
|
+
if (cmp < 0) {
|
158
|
+
new_node->left = n->left;
|
159
|
+
new_node->right = n;
|
160
|
+
n->left = NULL;
|
161
|
+
n->size = 1 + node_size(n->right);
|
162
|
+
} else {
|
163
|
+
new_node->right = n->right;
|
164
|
+
new_node->left = n;
|
165
|
+
n->right = NULL;
|
166
|
+
n->size = 1 + node_size(n->left);
|
138
167
|
}
|
139
|
-
tree->root = new_node;
|
140
|
-
tree->size += 1;
|
141
168
|
}
|
169
|
+
new_node->size = 1 + node_size(new_node->left) + node_size(new_node->right);
|
170
|
+
return new_node;
|
142
171
|
}
|
143
172
|
|
144
173
|
static VALUE get(splaytree *tree, VALUE key) {
|
145
174
|
int cmp;
|
175
|
+
|
146
176
|
if (!tree->root)
|
147
177
|
return Qnil;
|
148
|
-
|
149
|
-
splay(tree, key);
|
178
|
+
|
179
|
+
tree->root = splay(tree, tree->root, key);
|
150
180
|
cmp = tree->compare_function(key, tree->root->key);
|
151
181
|
if (cmp == 0) {
|
152
182
|
return tree->root->value;
|
@@ -154,29 +184,28 @@ static VALUE get(splaytree *tree, VALUE key) {
|
|
154
184
|
return Qnil;
|
155
185
|
}
|
156
186
|
|
157
|
-
static
|
158
|
-
int cmp;
|
159
|
-
splaytree_node *x
|
160
|
-
|
161
|
-
|
162
|
-
splay(tree, key);
|
163
|
-
cmp = tree->compare_function(key,
|
187
|
+
static splaytree_node* delete(splaytree *tree, splaytree_node *n, VALUE key, VALUE *deleted) {
|
188
|
+
int cmp, tsize;
|
189
|
+
splaytree_node *x;
|
190
|
+
|
191
|
+
tsize = n->size;
|
192
|
+
n = splay(tree, n, key);
|
193
|
+
cmp = tree->compare_function(key, n->key);
|
164
194
|
if (cmp == 0) {
|
165
|
-
deleted =
|
166
|
-
|
167
|
-
|
168
|
-
tree->root = tree->root->right;
|
195
|
+
*deleted = n->value;
|
196
|
+
if (!n->left) {
|
197
|
+
x = n->right;
|
169
198
|
} else {
|
170
|
-
x = tree->
|
171
|
-
|
172
|
-
splay(tree, key);
|
173
|
-
tree->root->right = x;
|
199
|
+
x = splay(tree, n->left, key);
|
200
|
+
x->right = n->right;
|
174
201
|
}
|
175
|
-
|
176
|
-
|
177
|
-
|
202
|
+
xfree(n);
|
203
|
+
if (x) {
|
204
|
+
x->size = tsize-1;
|
205
|
+
}
|
206
|
+
return x;
|
178
207
|
}
|
179
|
-
return
|
208
|
+
return n;
|
180
209
|
}
|
181
210
|
|
182
211
|
static splaytree* splaytree_each_node(splaytree *tree, splaytree_node *node, void (*each)(splaytree *tree_, splaytree_node *node_, void* args), void* arguments) {
|
@@ -201,7 +230,7 @@ static splaytree* splay_each(splaytree *tree, void (*each)(splaytree *tree, spla
|
|
201
230
|
|
202
231
|
// Methods to be called in Ruby
|
203
232
|
|
204
|
-
static
|
233
|
+
static VALUE id_compare_operator;
|
205
234
|
|
206
235
|
static int splaytree_compare_function(VALUE a, VALUE b) {
|
207
236
|
if (a == b) return 0;
|
@@ -211,8 +240,8 @@ static int splaytree_compare_function(VALUE a, VALUE b) {
|
|
211
240
|
if (x > y) return 1;
|
212
241
|
return -1;
|
213
242
|
}
|
214
|
-
if (TYPE(a) == T_STRING &&
|
215
|
-
|
243
|
+
if (TYPE(a) == T_STRING && rb_obj_is_kind_of(a, rb_cString) &&
|
244
|
+
TYPE(b) == T_STRING && rb_obj_is_kind_of(b, rb_cString)) {
|
216
245
|
return rb_str_cmp(a, b);
|
217
246
|
}
|
218
247
|
return FIX2INT(rb_funcall((VALUE) a, id_compare_operator, 1, (VALUE) b));
|
@@ -223,19 +252,39 @@ static VALUE splaytree_init(VALUE self)
|
|
223
252
|
return self;
|
224
253
|
}
|
225
254
|
|
226
|
-
static void recursively_mark_nodes(splaytree_node *node) {
|
227
|
-
if(node) {
|
228
|
-
rb_gc_mark(node->key);
|
229
|
-
rb_gc_mark(node->value);
|
230
|
-
recursively_mark_nodes(node->left);
|
231
|
-
recursively_mark_nodes(node->right);
|
232
|
-
}
|
233
|
-
}
|
234
|
-
|
235
255
|
static void splaytree_mark(void *ptr) {
|
256
|
+
ll_node *current, *new, *last, *old;
|
236
257
|
if (ptr) {
|
237
258
|
splaytree *tree = ptr;
|
238
|
-
|
259
|
+
|
260
|
+
if (tree->root) {
|
261
|
+
current = ALLOC(ll_node);
|
262
|
+
last = current;
|
263
|
+
current->node = tree->root;
|
264
|
+
current->next = NULL;
|
265
|
+
|
266
|
+
while(current) {
|
267
|
+
rb_gc_mark(current->node->key);
|
268
|
+
rb_gc_mark(current->node->value);
|
269
|
+
if (current->node->left) {
|
270
|
+
new = ALLOC(ll_node);
|
271
|
+
new->node = current->node->left;
|
272
|
+
new->next = NULL;
|
273
|
+
last->next = new;
|
274
|
+
last = new;
|
275
|
+
}
|
276
|
+
if (current->node->right) {
|
277
|
+
new = ALLOC(ll_node);
|
278
|
+
new->node = current->node->right;
|
279
|
+
new->next = NULL;
|
280
|
+
last->next = new;
|
281
|
+
last = new;
|
282
|
+
}
|
283
|
+
old = current;
|
284
|
+
current = current->next;
|
285
|
+
xfree(old);
|
286
|
+
}
|
287
|
+
}
|
239
288
|
}
|
240
289
|
}
|
241
290
|
|
@@ -243,8 +292,7 @@ static void splaytree_free(void *ptr) {
|
|
243
292
|
if (ptr) {
|
244
293
|
splaytree *tree = ptr;
|
245
294
|
recursively_free_nodes(tree->root);
|
246
|
-
|
247
|
-
free(tree);
|
295
|
+
xfree(tree);
|
248
296
|
}
|
249
297
|
}
|
250
298
|
|
@@ -255,7 +303,7 @@ static VALUE splaytree_alloc(VALUE klass) {
|
|
255
303
|
|
256
304
|
static VALUE splaytree_push(VALUE self, VALUE key, VALUE value) {
|
257
305
|
splaytree *tree = get_tree_from_self(self);
|
258
|
-
insert(tree, key, value);
|
306
|
+
tree->root = insert(tree, tree->root, key, value);
|
259
307
|
return value;
|
260
308
|
}
|
261
309
|
|
@@ -266,7 +314,8 @@ static VALUE splaytree_get(VALUE self, VALUE key) {
|
|
266
314
|
|
267
315
|
static VALUE splaytree_size(VALUE self) {
|
268
316
|
splaytree *tree = get_tree_from_self(self);
|
269
|
-
return INT2NUM(
|
317
|
+
if(!tree->root) { return INT2NUM(0); }
|
318
|
+
return INT2NUM(tree->root->size);
|
270
319
|
}
|
271
320
|
|
272
321
|
static VALUE splaytree_is_empty(VALUE self) {
|
@@ -317,19 +366,19 @@ static VALUE splaytree_max_key(VALUE self) {
|
|
317
366
|
}
|
318
367
|
|
319
368
|
static VALUE splaytree_delete(VALUE self, VALUE key) {
|
369
|
+
VALUE deleted = Qnil;
|
320
370
|
splaytree *tree = get_tree_from_self(self);
|
321
371
|
if(!tree->root)
|
322
372
|
return Qnil;
|
323
373
|
|
324
|
-
|
374
|
+
tree->root = delete(tree, tree->root, key, &deleted);
|
375
|
+
return deleted;
|
325
376
|
}
|
326
377
|
|
327
378
|
static VALUE splaytree_clear(VALUE self) {
|
328
379
|
splaytree *tree = get_tree_from_self(self);
|
329
380
|
recursively_free_nodes(tree->root);
|
330
381
|
tree->root = NULL;
|
331
|
-
tree->size = 0;
|
332
|
-
|
333
382
|
return Qnil;
|
334
383
|
}
|
335
384
|
|