amorim-algorithms 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.markdown +193 -0
  3. data/Gemfile +9 -0
  4. data/Manifest +51 -0
  5. data/README.markdown +87 -0
  6. data/Rakefile +22 -0
  7. data/algorithms.gemspec +23 -0
  8. data/benchmarks/deque.rb +17 -0
  9. data/benchmarks/sorts.rb +34 -0
  10. data/benchmarks/treemaps.rb +51 -0
  11. data/ext/algorithms/string/extconf.rb +4 -0
  12. data/ext/algorithms/string/string.c +68 -0
  13. data/ext/containers/bst/bst.c +247 -0
  14. data/ext/containers/bst/extconf.rb +4 -0
  15. data/ext/containers/deque/deque.c +247 -0
  16. data/ext/containers/deque/extconf.rb +4 -0
  17. data/ext/containers/rbtree_map/extconf.rb +4 -0
  18. data/ext/containers/rbtree_map/rbtree.c +498 -0
  19. data/ext/containers/splaytree_map/extconf.rb +4 -0
  20. data/ext/containers/splaytree_map/splaytree.c +419 -0
  21. data/lib/algorithms.rb +66 -0
  22. data/lib/algorithms/search.rb +84 -0
  23. data/lib/algorithms/sort.rb +368 -0
  24. data/lib/algorithms/string.rb +9 -0
  25. data/lib/containers/deque.rb +171 -0
  26. data/lib/containers/heap.rb +499 -0
  27. data/lib/containers/kd_tree.rb +110 -0
  28. data/lib/containers/priority_queue.rb +113 -0
  29. data/lib/containers/queue.rb +68 -0
  30. data/lib/containers/rb_tree_map.rb +398 -0
  31. data/lib/containers/splay_tree_map.rb +269 -0
  32. data/lib/containers/stack.rb +67 -0
  33. data/lib/containers/suffix_array.rb +68 -0
  34. data/lib/containers/trie.rb +182 -0
  35. data/spec/bst_gc_mark_spec.rb +25 -0
  36. data/spec/bst_spec.rb +25 -0
  37. data/spec/deque_gc_mark_spec.rb +18 -0
  38. data/spec/deque_spec.rb +108 -0
  39. data/spec/heap_spec.rb +131 -0
  40. data/spec/kd_expected_out.txt +10000 -0
  41. data/spec/kd_test_in.txt +10000 -0
  42. data/spec/kd_tree_spec.rb +34 -0
  43. data/spec/map_gc_mark_spec.rb +29 -0
  44. data/spec/priority_queue_spec.rb +75 -0
  45. data/spec/queue_spec.rb +61 -0
  46. data/spec/rb_tree_map_spec.rb +123 -0
  47. data/spec/search_spec.rb +28 -0
  48. data/spec/sort_spec.rb +29 -0
  49. data/spec/splay_tree_map_spec.rb +106 -0
  50. data/spec/stack_spec.rb +60 -0
  51. data/spec/string_spec.rb +15 -0
  52. data/spec/suffix_array_spec.rb +40 -0
  53. data/spec/trie_spec.rb +59 -0
  54. metadata +108 -0
@@ -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
+ xfree(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
+ xfree(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
+ xfree(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
+ xfree(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 VALUE 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
+ xfree(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
+ xfree(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
+ }