algorithms 0.3.0-jruby

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/History.txt +172 -0
  2. data/Manifest +43 -0
  3. data/README.markdown +93 -0
  4. data/Rakefile +31 -0
  5. data/algorithms.gemspec +33 -0
  6. data/benchmarks/deque.rb +17 -0
  7. data/benchmarks/sorts.rb +34 -0
  8. data/benchmarks/treemaps.rb +51 -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 +498 -0
  13. data/ext/containers/splaytree_map/extconf.rb +4 -0
  14. data/ext/containers/splaytree_map/splaytree.c +419 -0
  15. data/lib/algorithms.rb +68 -0
  16. data/lib/algorithms/search.rb +84 -0
  17. data/lib/algorithms/sort.rb +238 -0
  18. data/lib/containers/deque.rb +171 -0
  19. data/lib/containers/heap.rb +486 -0
  20. data/lib/containers/kd_tree.rb +110 -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_expected_out.txt +10000 -0
  32. data/spec/kd_test_in.txt +10000 -0
  33. data/spec/kd_tree_spec.rb +34 -0
  34. data/spec/map_gc_mark_spec.rb +27 -0
  35. data/spec/priority_queue_spec.rb +75 -0
  36. data/spec/queue_spec.rb +61 -0
  37. data/spec/rb_tree_map_spec.rb +123 -0
  38. data/spec/search_spec.rb +28 -0
  39. data/spec/sort_spec.rb +28 -0
  40. data/spec/splay_tree_map_spec.rb +106 -0
  41. data/spec/stack_spec.rb +60 -0
  42. data/spec/suffix_array_spec.rb +40 -0
  43. data/spec/trie_spec.rb +59 -0
  44. metadata +122 -0
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+ extension_name = "CSplayTreeMap"
3
+ dir_config(extension_name)
4
+ create_makefile(extension_name)
@@ -0,0 +1,419 @@
1
+ #include "ruby.h"
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
+
9
+ typedef struct struct_splaytree_node {
10
+ VALUE key;
11
+ VALUE value;
12
+ int size;
13
+ struct struct_splaytree_node *left;
14
+ struct struct_splaytree_node *right;
15
+ } splaytree_node;
16
+
17
+ typedef struct {
18
+ int (*compare_function)(VALUE key1, VALUE key2);
19
+ splaytree_node *root;
20
+ } splaytree;
21
+
22
+ typedef struct struct_ll_node {
23
+ splaytree_node *node;
24
+ struct struct_ll_node *next;
25
+ } ll_node;
26
+
27
+ static void recursively_free_nodes(splaytree_node *node) {
28
+ if(node) {
29
+ recursively_free_nodes(node->left);
30
+ recursively_free_nodes(node->right);
31
+ free(node);
32
+ }
33
+ return;
34
+ }
35
+
36
+ static splaytree* get_tree_from_self(VALUE self) {
37
+ splaytree *tree;
38
+ Data_Get_Struct(self, splaytree, tree);
39
+ return tree;
40
+ }
41
+
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;
46
+
47
+ if (!n) return n;
48
+
49
+ N.left = N.right = NULL;
50
+ l = r = &N;
51
+ root_size = node_size(n);
52
+ l_size = r_size = 0;
53
+
54
+ while(1) {
55
+ cmp = tree->compare_function(key, n->key);
56
+ if (cmp == -1) {
57
+ if (!n->left) break;
58
+ cmp2 = tree->compare_function(key, n->left->key);
59
+ if (cmp2 == -1) {
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;
66
+ }
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);
74
+ if (cmp2 == 1) {
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;
81
+ }
82
+ l->right = n;
83
+ l = n;
84
+ n = n->right;
85
+ l_size += 1 + node_size(l->left);
86
+ } else {
87
+ break;
88
+ }
89
+ }
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;
111
+ }
112
+
113
+ static int height(splaytree_node *h) {
114
+ int left_height, right_height;
115
+
116
+ if(!h) { return 0; }
117
+
118
+ left_height = 1 + height(h->left);
119
+ right_height = 1 + height(h->right);
120
+
121
+ return left_height > right_height ? left_height : right_height;
122
+ }
123
+
124
+ static splaytree* create_splaytree(int (*compare_function)(VALUE, VALUE)) {
125
+ splaytree *tree = ALLOC(splaytree);
126
+ tree->compare_function = compare_function;
127
+ tree->root = NULL;
128
+ return tree;
129
+ }
130
+
131
+ static splaytree_node* create_node(VALUE key, VALUE value) {
132
+ splaytree_node *new_node = ALLOC(splaytree_node);
133
+ new_node->key = key;
134
+ new_node->value = value;
135
+ new_node->left = NULL;
136
+ new_node->right = NULL;
137
+ return new_node;
138
+ }
139
+
140
+ static splaytree_node* insert(splaytree *tree, splaytree_node *n, VALUE key, VALUE value) {
141
+ int cmp;
142
+ splaytree_node *new_node;
143
+
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
+ }
151
+ }
152
+ new_node = create_node(key, value);
153
+ if (!n) {
154
+ new_node->left = new_node->right = NULL;
155
+ } else {
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);
167
+ }
168
+ }
169
+ new_node->size = 1 + node_size(new_node->left) + node_size(new_node->right);
170
+ return new_node;
171
+ }
172
+
173
+ static VALUE get(splaytree *tree, VALUE key) {
174
+ int cmp;
175
+
176
+ if (!tree->root)
177
+ return Qnil;
178
+
179
+ tree->root = splay(tree, tree->root, key);
180
+ cmp = tree->compare_function(key, tree->root->key);
181
+ if (cmp == 0) {
182
+ return tree->root->value;
183
+ }
184
+ return Qnil;
185
+ }
186
+
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);
194
+ if (cmp == 0) {
195
+ *deleted = n->value;
196
+ if (!n->left) {
197
+ x = n->right;
198
+ } else {
199
+ x = splay(tree, n->left, key);
200
+ x->right = n->right;
201
+ }
202
+ free(n);
203
+ if (x) {
204
+ x->size = tsize-1;
205
+ }
206
+ return x;
207
+ }
208
+ return n;
209
+ }
210
+
211
+ static splaytree* splaytree_each_node(splaytree *tree, splaytree_node *node, void (*each)(splaytree *tree_, splaytree_node *node_, void* args), void* arguments) {
212
+ if (!node)
213
+ return NULL;
214
+
215
+ if (node->left)
216
+ splaytree_each_node(tree, node->left, each, arguments);
217
+
218
+ (*each)(tree, node, arguments);
219
+
220
+ if (node->right)
221
+ splaytree_each_node(tree, node->right, each, arguments);
222
+ return tree;
223
+ }
224
+
225
+ static splaytree* splay_each(splaytree *tree, void (*each)(splaytree *tree, splaytree_node *node, void *args), void* arguments) {
226
+ if (tree->root)
227
+ splaytree_each_node(tree, tree->root, each, arguments);
228
+ return tree;
229
+ }
230
+
231
+ // Methods to be called in Ruby
232
+
233
+ static int id_compare_operator;
234
+
235
+ static int splaytree_compare_function(VALUE a, VALUE b) {
236
+ if (a == b) return 0;
237
+ if (FIXNUM_P(a) && FIXNUM_P(b)) {
238
+ long x = FIX2LONG(a), y = FIX2LONG(b);
239
+ if (x == y) return 0;
240
+ if (x > y) return 1;
241
+ return -1;
242
+ }
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)) {
245
+ return rb_str_cmp(a, b);
246
+ }
247
+ return FIX2INT(rb_funcall((VALUE) a, id_compare_operator, 1, (VALUE) b));
248
+ }
249
+
250
+ static VALUE splaytree_init(VALUE self)
251
+ {
252
+ return self;
253
+ }
254
+
255
+ static void splaytree_mark(void *ptr) {
256
+ ll_node *current, *new, *last, *old;
257
+ if (ptr) {
258
+ splaytree *tree = ptr;
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
+ free(old);
286
+ }
287
+ }
288
+ }
289
+ }
290
+
291
+ static void splaytree_free(void *ptr) {
292
+ if (ptr) {
293
+ splaytree *tree = ptr;
294
+ recursively_free_nodes(tree->root);
295
+ free(tree);
296
+ }
297
+ }
298
+
299
+ static VALUE splaytree_alloc(VALUE klass) {
300
+ splaytree *tree = create_splaytree(&splaytree_compare_function);
301
+ return Data_Wrap_Struct(klass, splaytree_mark, splaytree_free, tree);
302
+ }
303
+
304
+ static VALUE splaytree_push(VALUE self, VALUE key, VALUE value) {
305
+ splaytree *tree = get_tree_from_self(self);
306
+ tree->root = insert(tree, tree->root, key, value);
307
+ return value;
308
+ }
309
+
310
+ static VALUE splaytree_get(VALUE self, VALUE key) {
311
+ splaytree *tree = get_tree_from_self(self);
312
+ return get(tree, key);
313
+ }
314
+
315
+ static VALUE splaytree_size(VALUE self) {
316
+ splaytree *tree = get_tree_from_self(self);
317
+ if(!tree->root) { return INT2NUM(0); }
318
+ return INT2NUM(tree->root->size);
319
+ }
320
+
321
+ static VALUE splaytree_is_empty(VALUE self) {
322
+ splaytree *tree = get_tree_from_self(self);
323
+ return (tree->root ? Qfalse : Qtrue);
324
+ }
325
+
326
+ static VALUE splaytree_height(VALUE self) {
327
+ splaytree *tree = get_tree_from_self(self);
328
+ return INT2NUM(height(tree->root));
329
+ }
330
+
331
+ static VALUE splaytree_has_key(VALUE self, VALUE key) {
332
+ splaytree *tree = get_tree_from_self(self);
333
+ if(!tree->root) { return Qfalse; }
334
+ if(get(tree, key) == Qnil)
335
+ return Qfalse;
336
+
337
+ return Qtrue;
338
+ }
339
+
340
+ static VALUE splaytree_min_key(VALUE self) {
341
+ splaytree *tree = get_tree_from_self(self);
342
+ splaytree_node *node;
343
+
344
+ if(!tree->root)
345
+ return Qnil;
346
+
347
+ node = tree->root;
348
+ while (node->left)
349
+ node = node->left;
350
+
351
+ return node->key;
352
+ }
353
+
354
+ static VALUE splaytree_max_key(VALUE self) {
355
+ splaytree *tree = get_tree_from_self(self);
356
+ splaytree_node *node;
357
+
358
+ if(!tree->root)
359
+ return Qnil;
360
+
361
+ node = tree->root;
362
+ while (node->right)
363
+ node = node->right;
364
+
365
+ return node->key;
366
+ }
367
+
368
+ static VALUE splaytree_delete(VALUE self, VALUE key) {
369
+ VALUE deleted = Qnil;
370
+ splaytree *tree = get_tree_from_self(self);
371
+ if(!tree->root)
372
+ return Qnil;
373
+
374
+ tree->root = delete(tree, tree->root, key, &deleted);
375
+ return deleted;
376
+ }
377
+
378
+ static VALUE splaytree_clear(VALUE self) {
379
+ splaytree *tree = get_tree_from_self(self);
380
+ recursively_free_nodes(tree->root);
381
+ tree->root = NULL;
382
+ return Qnil;
383
+ }
384
+
385
+ static void splaytree_each_helper(splaytree *tree, splaytree_node *node, void *args) {
386
+ rb_yield(rb_ary_new3(2, node->key, node->value));
387
+ };
388
+
389
+ static VALUE splaytree_each(VALUE self) {
390
+ splaytree *tree = get_tree_from_self(self);
391
+ splay_each(tree, &splaytree_each_helper, NULL);
392
+ return self;
393
+ }
394
+
395
+ static VALUE CSplayTree;
396
+ static VALUE mContainers;
397
+
398
+ void Init_CSplayTreeMap() {
399
+ id_compare_operator = rb_intern("<=>");
400
+
401
+ mContainers = rb_define_module("Containers");
402
+ CSplayTree = rb_define_class_under(mContainers, "CSplayTreeMap", rb_cObject);
403
+ rb_define_alloc_func(CSplayTree, splaytree_alloc);
404
+ rb_define_method(CSplayTree, "initialize", splaytree_init, 0);
405
+ rb_define_method(CSplayTree, "push", splaytree_push, 2);
406
+ rb_define_method(CSplayTree, "clear", splaytree_clear, 0);
407
+ rb_define_alias(CSplayTree, "[]=", "push");
408
+ rb_define_method(CSplayTree, "size", splaytree_size, 0);
409
+ rb_define_method(CSplayTree, "empty?", splaytree_is_empty, 0);
410
+ rb_define_method(CSplayTree, "height", splaytree_height, 0);
411
+ rb_define_method(CSplayTree, "min_key", splaytree_min_key, 0);
412
+ rb_define_method(CSplayTree, "max_key", splaytree_max_key, 0);
413
+ rb_define_method(CSplayTree, "each", splaytree_each, 0);
414
+ rb_define_method(CSplayTree, "get", splaytree_get, 1);
415
+ rb_define_alias(CSplayTree, "[]", "get");
416
+ rb_define_method(CSplayTree, "has_key?", splaytree_has_key, 1);
417
+ rb_define_method(CSplayTree, "delete", splaytree_delete, 1);
418
+ rb_include_module(CSplayTree, rb_eval_string("Enumerable"));
419
+ }
@@ -0,0 +1,68 @@
1
+ =begin rdoc
2
+ The 'Algorithms and Containers' library is an effort to provide a set of commonly used
3
+ algorithms and containers to Ruby programmers.
4
+
5
+ This is a Google Summer of Code 2008 project
6
+
7
+ Written by Kanwei Li, mentored by Austin Ziegler
8
+
9
+ To avoid typing Containers::xxx to initialize containers, include the Containers module.
10
+
11
+ require 'algorithms'
12
+ include Containers
13
+
14
+ tree = RBTreeMap.new
15
+
16
+ instead of:
17
+
18
+ require 'algorithms'
19
+
20
+ tree = Containers::RBTreeMap.new
21
+
22
+ Done so far:
23
+ * Heaps - Containers::Heap, Containers::MaxHeap, Containers::MinHeap
24
+ * Priority Queue - Containers::PriorityQueue
25
+ * Stack - Containers::Stack
26
+ * Queue - Containers::Queue
27
+ * Deque - Containers::Deque, Containers::CDeque (C extension), Containers::RubyDeque
28
+ * Red-Black Trees - Containers::RBTreeMap, Containers::CRBTreeMap (C extension), Containers::RubyRBTreeMap
29
+ * Splay Trees - Containers::SplayTreeMap
30
+ * Tries - Containers::Trie
31
+ * Suffix Array - Containers::SuffixArray
32
+ * kd Tree - Containers::KDTree
33
+
34
+ * Search algorithms
35
+ - Binary Search - Algorithms::Search.binary_search
36
+ - Knuth-Morris-Pratt - Algorithms::Search.kmp_search
37
+ * Sort algorithms
38
+ - Bubble sort - Algorithms::Sort.bubble_sort
39
+ - Comb sort - Algorithms::Sort.comb_sort
40
+ - Selection sort - Algorithms::Sort.selection_sort
41
+ - Heapsort - Algorithms::Sort.heapsort
42
+ - Insertion sort - Algorithms::Sort.insertion_sort
43
+ - Shell sort - Algorithms::Sort.shell_sort
44
+ - Quicksort - Algorithms::Sort.quicksort
45
+ - Mergesort - Algorithms::Sort.mergesort
46
+ =end
47
+
48
+ module Algorithms; end
49
+ module Containers; end
50
+
51
+ begin
52
+ require 'CBst'
53
+ Containers::Bst = Containers::CBst
54
+ rescue LoadError # C Version could not be found
55
+ end
56
+
57
+ require 'algorithms/search'
58
+ require 'algorithms/sort'
59
+ require 'containers/heap'
60
+ require 'containers/stack'
61
+ require 'containers/deque'
62
+ require 'containers/queue'
63
+ require 'containers/priority_queue'
64
+ require 'containers/rb_tree_map'
65
+ require 'containers/splay_tree_map'
66
+ require 'containers/suffix_array'
67
+ require 'containers/trie'
68
+ require 'containers/kd_tree'