algorithms 0.0.1 → 0.1.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.
- data/History.txt +139 -2
- data/Manifest +31 -8
- data/README +90 -0
- data/Rakefile +22 -9
- data/algorithms.gemspec +28 -101
- data/benchmark.rb +29 -27
- data/benchmarks/rbench.rb +16 -0
- data/benchmarks/rbench/column.rb +26 -0
- data/benchmarks/rbench/group.rb +43 -0
- data/benchmarks/rbench/report.rb +53 -0
- data/benchmarks/rbench/runner.rb +109 -0
- data/benchmarks/rbench/summary.rb +51 -0
- data/benchmarks/sorts.rb +33 -0
- data/ext/containers/bst/bst.c +205 -0
- data/ext/containers/{priority_queue → bst}/extconf.rb +1 -1
- data/ext/containers/deque/deque.c +233 -0
- data/ext/containers/deque/extconf.rb +4 -0
- data/ext/containers/tree_map/extconf.rb +1 -1
- data/ext/containers/tree_map/rbtree.c +73 -25
- data/lib/algorithms.rb +65 -6
- data/lib/algorithms/search.rb +84 -0
- data/lib/algorithms/sort.rb +238 -0
- data/lib/containers/deque.rb +176 -0
- data/lib/containers/heap.rb +451 -111
- data/lib/containers/kd_tree.rb +87 -0
- data/lib/containers/priority_queue.rb +107 -508
- data/lib/containers/queue.rb +62 -23
- data/lib/containers/rb_tree_map.rb +398 -0
- data/lib/containers/splay_tree_map.rb +274 -0
- data/lib/containers/stack.rb +59 -21
- data/lib/containers/suffix_array.rb +68 -0
- data/lib/containers/trie.rb +182 -0
- data/lib/graphs/graph.rb +25 -0
- data/spec/bst_spec.rb +31 -0
- data/spec/deque_spec.rb +108 -0
- data/spec/heap_spec.rb +111 -66
- data/spec/kd_tree_spec.rb +89 -0
- data/spec/priority_queue_spec.rb +71 -27
- data/spec/queue_spec.rb +53 -45
- 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 +102 -0
- data/spec/stack_spec.rb +56 -49
- data/spec/suffix_array_spec.rb +40 -0
- data/spec/trie_spec.rb +59 -0
- metadata +54 -32
- data/README.txt +0 -58
- data/ext/containers/priority_queue/priority_queue.c +0 -948
- data/ext/containers/tree_map/Rakefile +0 -4
- data/lib/containers/hash.rb +0 -0
- data/lib/containers/tree_map.rb +0 -265
- data/spec/priority_queue_test.rb +0 -371
- data/spec/tree_map_spec.rb +0 -99
@@ -0,0 +1,233 @@
|
|
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_free(deque *deque) {
|
60
|
+
free_nodes(deque->front);
|
61
|
+
free(deque);
|
62
|
+
}
|
63
|
+
|
64
|
+
static VALUE deque_alloc(VALUE klass) {
|
65
|
+
deque *deque = create_deque();
|
66
|
+
return Data_Wrap_Struct(klass, NULL, deque_free, deque);
|
67
|
+
}
|
68
|
+
|
69
|
+
static VALUE deque_push_front(VALUE self, VALUE obj) {
|
70
|
+
deque *deque = get_deque_from_self(self);
|
71
|
+
deque_node *node = create_node(obj);
|
72
|
+
if(deque->front) {
|
73
|
+
node->right = deque->front;
|
74
|
+
deque->front->left = node;
|
75
|
+
deque->front = node;
|
76
|
+
}
|
77
|
+
else {
|
78
|
+
deque->front = node;
|
79
|
+
deque->back = node;
|
80
|
+
}
|
81
|
+
deque->size++;
|
82
|
+
return obj;
|
83
|
+
}
|
84
|
+
|
85
|
+
static VALUE deque_push_back(VALUE self, VALUE obj) {
|
86
|
+
deque *deque = get_deque_from_self(self);
|
87
|
+
deque_node *node = create_node(obj);
|
88
|
+
if(deque->back) {
|
89
|
+
node->left = deque->back;
|
90
|
+
deque->back->right = node;
|
91
|
+
deque->back = node;
|
92
|
+
}
|
93
|
+
else {
|
94
|
+
deque->front = node;
|
95
|
+
deque->back = node;
|
96
|
+
}
|
97
|
+
deque->size++;
|
98
|
+
return obj;
|
99
|
+
}
|
100
|
+
|
101
|
+
static VALUE deque_pop_front(VALUE self) {
|
102
|
+
deque *deque = get_deque_from_self(self);
|
103
|
+
VALUE obj;
|
104
|
+
if(!deque->front)
|
105
|
+
return Qnil;
|
106
|
+
deque_node *node = deque->front;
|
107
|
+
obj = node->obj;
|
108
|
+
if(deque->size == 1) {
|
109
|
+
clear_deque(deque);
|
110
|
+
return obj;
|
111
|
+
}
|
112
|
+
deque->front->right->left = NULL;
|
113
|
+
deque->front = deque->front->right;
|
114
|
+
deque->size--;
|
115
|
+
return obj;
|
116
|
+
}
|
117
|
+
|
118
|
+
static VALUE deque_front(VALUE self) {
|
119
|
+
deque *deque = get_deque_from_self(self);
|
120
|
+
if(deque->front)
|
121
|
+
return deque->front->obj;
|
122
|
+
|
123
|
+
return Qnil;
|
124
|
+
}
|
125
|
+
|
126
|
+
static VALUE deque_back(VALUE self) {
|
127
|
+
deque *deque = get_deque_from_self(self);
|
128
|
+
if(deque->back)
|
129
|
+
return deque->back->obj;
|
130
|
+
|
131
|
+
return Qnil;
|
132
|
+
}
|
133
|
+
|
134
|
+
static VALUE deque_pop_back(VALUE self) {
|
135
|
+
deque *deque = get_deque_from_self(self);
|
136
|
+
VALUE obj;
|
137
|
+
if(!deque->back)
|
138
|
+
return Qnil;
|
139
|
+
deque_node *node = deque->back;
|
140
|
+
obj = node->obj;
|
141
|
+
if(deque->size == 1) {
|
142
|
+
clear_deque(deque);
|
143
|
+
return obj;
|
144
|
+
}
|
145
|
+
deque->back->left->right = NULL;
|
146
|
+
deque->back = deque->back->left;
|
147
|
+
deque->size--;
|
148
|
+
return obj;
|
149
|
+
}
|
150
|
+
|
151
|
+
static VALUE deque_clear(VALUE self) {
|
152
|
+
deque *deque = get_deque_from_self(self);
|
153
|
+
clear_deque(deque);
|
154
|
+
return Qnil;
|
155
|
+
}
|
156
|
+
|
157
|
+
static VALUE deque_size(VALUE self) {
|
158
|
+
deque *deque = get_deque_from_self(self);
|
159
|
+
return INT2NUM(deque->size);
|
160
|
+
}
|
161
|
+
|
162
|
+
static VALUE deque_is_empty(VALUE self) {
|
163
|
+
deque *deque = get_deque_from_self(self);
|
164
|
+
return (deque->size == 0) ? Qtrue : Qfalse;
|
165
|
+
}
|
166
|
+
|
167
|
+
static VALUE deque_each_forward(VALUE self) {
|
168
|
+
deque *deque = get_deque_from_self(self);
|
169
|
+
deque_node *node = deque->front;
|
170
|
+
while(node) {
|
171
|
+
rb_yield(node->obj);
|
172
|
+
node = node->right;
|
173
|
+
}
|
174
|
+
return self;
|
175
|
+
}
|
176
|
+
|
177
|
+
static VALUE deque_each_backward(VALUE self) {
|
178
|
+
deque *deque = get_deque_from_self(self);
|
179
|
+
deque_node *node = deque->back;
|
180
|
+
while(node) {
|
181
|
+
rb_yield(node->obj);
|
182
|
+
node = node->left;
|
183
|
+
}
|
184
|
+
return self;
|
185
|
+
}
|
186
|
+
|
187
|
+
static VALUE deque_init(int argc, VALUE *argv, VALUE self)
|
188
|
+
{
|
189
|
+
int len, i;
|
190
|
+
VALUE ary;
|
191
|
+
|
192
|
+
if(argc == 0) {
|
193
|
+
return self;
|
194
|
+
}
|
195
|
+
else if(argc > 1) {
|
196
|
+
rb_raise(rb_eArgError, "wrong number of arguments");
|
197
|
+
}
|
198
|
+
else {
|
199
|
+
ary = rb_check_array_type(argv[0]);
|
200
|
+
if(!NIL_P(ary)) {
|
201
|
+
len = RARRAY_LEN(ary);
|
202
|
+
for (i = 0; i < len; i++) {
|
203
|
+
deque_push_back(self, RARRAY_PTR(ary)[i]);
|
204
|
+
}
|
205
|
+
}
|
206
|
+
}
|
207
|
+
return self;
|
208
|
+
}
|
209
|
+
|
210
|
+
static VALUE cDeque;
|
211
|
+
static VALUE mContainers;
|
212
|
+
|
213
|
+
void Init_CDeque() {
|
214
|
+
mContainers = rb_define_module("Containers");
|
215
|
+
cDeque = rb_define_class_under(mContainers, "CDeque", rb_cObject);
|
216
|
+
rb_define_alloc_func(cDeque, deque_alloc);
|
217
|
+
rb_define_method(cDeque, "initialize", deque_init, -1);
|
218
|
+
rb_define_method(cDeque, "push_front", deque_push_front, 1);
|
219
|
+
rb_define_method(cDeque, "push_back", deque_push_back, 1);
|
220
|
+
rb_define_method(cDeque, "clear", deque_clear, 0);
|
221
|
+
rb_define_method(cDeque, "front", deque_front, 0);
|
222
|
+
rb_define_method(cDeque, "back", deque_back, 0);
|
223
|
+
rb_define_method(cDeque, "pop_front", deque_pop_front, 0);
|
224
|
+
rb_define_method(cDeque, "pop_back", deque_pop_back, 0);
|
225
|
+
rb_define_method(cDeque, "size", deque_size, 0);
|
226
|
+
rb_define_alias(cDeque, "length", "size");
|
227
|
+
rb_define_method(cDeque, "empty?", deque_is_empty, 0);
|
228
|
+
rb_define_method(cDeque, "each_forward", deque_each_forward, 0);
|
229
|
+
rb_define_method(cDeque, "each_backward", deque_each_backward, 0);
|
230
|
+
rb_define_alias(cDeque, "each", "each_forward");
|
231
|
+
rb_define_alias(cDeque, "reverse_each", "each_backward");
|
232
|
+
rb_include_module(cDeque, rb_eval_string("Enumerable"));
|
233
|
+
}
|
@@ -122,6 +122,7 @@ static rbtree_node* fixup(rbtree_node *h) {
|
|
122
122
|
|
123
123
|
return set_num_nodes(h);
|
124
124
|
}
|
125
|
+
|
125
126
|
static rbtree* create_rbtree(int (*compare_function)(VALUE, VALUE)) {
|
126
127
|
rbtree *tree = ALLOC(rbtree);
|
127
128
|
tree->black_height = 0;
|
@@ -146,11 +147,6 @@ static rbtree_node* insert(rbtree *tree, rbtree_node *node, VALUE key, VALUE val
|
|
146
147
|
return new_node;
|
147
148
|
}
|
148
149
|
|
149
|
-
// Do a top-down breaking of 4-nodes
|
150
|
-
if ( isred(node->left) && isred(node->right) ) {
|
151
|
-
colorflip(node);
|
152
|
-
}
|
153
|
-
|
154
150
|
// Insert left or right, recursively
|
155
151
|
cmp = tree->compare_function(key, node->key);
|
156
152
|
if (cmp == 0) { node->value = value; }
|
@@ -160,7 +156,9 @@ static rbtree_node* insert(rbtree *tree, rbtree_node *node, VALUE key, VALUE val
|
|
160
156
|
// Fix our tree to keep left-lean
|
161
157
|
if (isred(node->right)) { node = rotate_left(node); }
|
162
158
|
if (isred(node->left) && isred(node->left->left)) { node = rotate_right(node); }
|
163
|
-
|
159
|
+
if ( isred(node->left) && isred(node->right) ) {
|
160
|
+
colorflip(node);
|
161
|
+
}
|
164
162
|
return set_num_nodes(node);
|
165
163
|
}
|
166
164
|
|
@@ -191,34 +189,40 @@ static VALUE max_key(rbtree_node *node) {
|
|
191
189
|
return max_key(node->right);
|
192
190
|
}
|
193
191
|
|
194
|
-
static rbtree_node* delete_min(rbtree_node *h) {
|
195
|
-
if ( !
|
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);
|
196
197
|
return NULL;
|
198
|
+
}
|
197
199
|
|
198
200
|
if ( !isred(h->left) && !isred(h->left->left) )
|
199
201
|
h = move_red_left(h);
|
200
202
|
|
201
|
-
h->left = delete_min(h->left);
|
203
|
+
h->left = delete_min(h->left, deleted_value);
|
202
204
|
|
203
205
|
return fixup(h);
|
204
206
|
}
|
205
207
|
|
206
|
-
static rbtree_node* delete_max(rbtree_node *h) {
|
208
|
+
static rbtree_node* delete_max(rbtree_node *h, VALUE *deleted_value) {
|
207
209
|
if ( isred(h->left) )
|
208
210
|
h = rotate_right(h);
|
209
211
|
|
210
|
-
if ( !
|
212
|
+
if ( !h->right ) {
|
213
|
+
*deleted_value = h->value;
|
214
|
+
free(h);
|
211
215
|
return NULL;
|
216
|
+
}
|
212
217
|
|
213
218
|
if ( !isred(h->right) && !isred(h->right->left) )
|
214
219
|
h = move_red_right(h);
|
215
220
|
|
216
|
-
h->right = delete_max(h->right);
|
221
|
+
h->right = delete_max(h->right, deleted_value);
|
217
222
|
|
218
223
|
return fixup(h);
|
219
224
|
}
|
220
225
|
|
221
|
-
|
222
226
|
static rbtree_node* delete(rbtree *tree, rbtree_node *node, VALUE key, VALUE *deleted_value) {
|
223
227
|
int cmp;
|
224
228
|
VALUE minimum_key;
|
@@ -232,9 +236,11 @@ static rbtree_node* delete(rbtree *tree, rbtree_node *node, VALUE key, VALUE *de
|
|
232
236
|
else {
|
233
237
|
if ( isred(node->left) )
|
234
238
|
node = rotate_right(node);
|
235
|
-
|
236
|
-
|
239
|
+
|
240
|
+
cmp = tree->compare_function(key, node->key);
|
241
|
+
if ( (cmp == 0) && !node->right ) {
|
237
242
|
*deleted_value = node->value;
|
243
|
+
free(node);
|
238
244
|
return NULL;
|
239
245
|
}
|
240
246
|
|
@@ -247,7 +253,7 @@ static rbtree_node* delete(rbtree *tree, rbtree_node *node, VALUE key, VALUE *de
|
|
247
253
|
minimum_key = min_key(node->right);
|
248
254
|
node->value = get(tree, node->right, minimum_key);
|
249
255
|
node->key = minimum_key;
|
250
|
-
node->right = delete_min(node->right);
|
256
|
+
node->right = delete_min(node->right, NULL);
|
251
257
|
}
|
252
258
|
else {
|
253
259
|
node->right = delete(tree, node->right, key, deleted_value);
|
@@ -273,7 +279,6 @@ static rbtree* rbt_each(rbtree *tree, void (*each)(rbtree *tree, rbtree_node *no
|
|
273
279
|
rbtree_each_node(tree, tree->root, each, arguments);
|
274
280
|
return tree;
|
275
281
|
}
|
276
|
-
|
277
282
|
|
278
283
|
// Methods to be called in Ruby
|
279
284
|
|
@@ -298,7 +303,7 @@ static VALUE rbtree_alloc(VALUE klass) {
|
|
298
303
|
return Data_Wrap_Struct(klass, NULL, rbtree_free, tree);
|
299
304
|
}
|
300
305
|
|
301
|
-
static VALUE
|
306
|
+
static VALUE rbtree_push(VALUE self, VALUE key, VALUE value) {
|
302
307
|
rbtree *tree = get_tree_from_self(self);
|
303
308
|
tree->root = insert(tree, tree->root, key, value);
|
304
309
|
return value;
|
@@ -314,13 +319,19 @@ static VALUE rbtree_size(VALUE self) {
|
|
314
319
|
return INT2NUM(size(tree->root));
|
315
320
|
}
|
316
321
|
|
322
|
+
static VALUE rbtree_is_empty(VALUE self) {
|
323
|
+
rbtree *tree = get_tree_from_self(self);
|
324
|
+
return (tree->root ? Qfalse : Qtrue);
|
325
|
+
}
|
326
|
+
|
317
327
|
static VALUE rbtree_height(VALUE self) {
|
318
328
|
rbtree *tree = get_tree_from_self(self);
|
319
329
|
return INT2NUM(height(tree->root));
|
320
330
|
}
|
321
331
|
|
322
|
-
static VALUE
|
332
|
+
static VALUE rbtree_has_key(VALUE self, VALUE key) {
|
323
333
|
rbtree *tree = get_tree_from_self(self);
|
334
|
+
if(!tree->root) { return Qfalse; }
|
324
335
|
if(get(tree, tree->root, key) == Qnil)
|
325
336
|
return Qfalse;
|
326
337
|
|
@@ -350,7 +361,41 @@ static VALUE rbtree_delete(VALUE self, VALUE key) {
|
|
350
361
|
return Qnil;
|
351
362
|
|
352
363
|
tree->root = delete(tree, tree->root, key, &deleted_value);
|
364
|
+
if(tree->root)
|
365
|
+
tree->root->color = BLACK;
|
366
|
+
|
367
|
+
if(deleted_value) {
|
368
|
+
return deleted_value;
|
369
|
+
}
|
370
|
+
|
371
|
+
return Qnil;
|
372
|
+
}
|
373
|
+
|
374
|
+
static VALUE rbtree_delete_min(VALUE self) {
|
375
|
+
VALUE deleted_value;
|
376
|
+
rbtree *tree = get_tree_from_self(self);
|
353
377
|
if(!tree->root)
|
378
|
+
return Qnil;
|
379
|
+
|
380
|
+
tree->root = delete_min(tree->root, &deleted_value);
|
381
|
+
if(tree->root)
|
382
|
+
tree->root->color = BLACK;
|
383
|
+
|
384
|
+
if(deleted_value) {
|
385
|
+
return deleted_value;
|
386
|
+
}
|
387
|
+
|
388
|
+
return Qnil;
|
389
|
+
}
|
390
|
+
|
391
|
+
static VALUE rbtree_delete_max(VALUE self) {
|
392
|
+
VALUE deleted_value;
|
393
|
+
rbtree *tree = get_tree_from_self(self);
|
394
|
+
if(!tree->root)
|
395
|
+
return Qnil;
|
396
|
+
|
397
|
+
tree->root = delete_max(tree->root, &deleted_value);
|
398
|
+
if(tree->root)
|
354
399
|
tree->root->color = BLACK;
|
355
400
|
|
356
401
|
if(deleted_value) {
|
@@ -373,23 +418,26 @@ static VALUE rbtree_each(VALUE self) {
|
|
373
418
|
static VALUE cRBTree;
|
374
419
|
static VALUE mContainers;
|
375
420
|
|
376
|
-
void
|
421
|
+
void Init_CRBTreeMap() {
|
377
422
|
id_compare_operator = rb_intern("<=>");
|
378
423
|
|
379
424
|
mContainers = rb_define_module("Containers");
|
380
|
-
cRBTree = rb_define_class_under(mContainers, "
|
425
|
+
cRBTree = rb_define_class_under(mContainers, "CRBTreeMap", rb_cObject);
|
381
426
|
rb_define_alloc_func(cRBTree, rbtree_alloc);
|
382
427
|
rb_define_method(cRBTree, "initialize", rbtree_init, 0);
|
383
|
-
rb_define_method(cRBTree, "
|
384
|
-
rb_define_alias(cRBTree, "[]=", "
|
428
|
+
rb_define_method(cRBTree, "push", rbtree_push, 2);
|
429
|
+
rb_define_alias(cRBTree, "[]=", "push");
|
385
430
|
rb_define_method(cRBTree, "size", rbtree_size, 0);
|
431
|
+
rb_define_method(cRBTree, "empty?", rbtree_is_empty, 0);
|
386
432
|
rb_define_method(cRBTree, "height", rbtree_height, 0);
|
387
433
|
rb_define_method(cRBTree, "min_key", rbtree_min_key, 0);
|
388
434
|
rb_define_method(cRBTree, "max_key", rbtree_max_key, 0);
|
435
|
+
rb_define_method(cRBTree, "delete_min", rbtree_delete_min, 0);
|
436
|
+
rb_define_method(cRBTree, "delete_max", rbtree_delete_max, 0);
|
389
437
|
rb_define_method(cRBTree, "each", rbtree_each, 0);
|
390
438
|
rb_define_method(cRBTree, "get", rbtree_get, 1);
|
391
439
|
rb_define_alias(cRBTree, "[]", "get");
|
392
|
-
rb_define_method(cRBTree, "
|
440
|
+
rb_define_method(cRBTree, "has_key?", rbtree_has_key, 1);
|
393
441
|
rb_define_method(cRBTree, "delete", rbtree_delete, 1);
|
394
442
|
rb_include_module(cRBTree, rb_eval_string("Enumerable"));
|
395
|
-
}
|
443
|
+
}
|