kanwei-algorithms 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/History.txt +168 -0
  2. data/Manifest +41 -0
  3. data/README.markdown +92 -0
  4. data/Rakefile +31 -0
  5. data/algorithms.gemspec +32 -0
  6. data/benchmarks/deque.rb +17 -0
  7. data/benchmarks/sorts.rb +34 -0
  8. data/benchmarks/treemaps.rb +36 -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 +473 -0
  13. data/ext/containers/splaytree_map/extconf.rb +4 -0
  14. data/ext/containers/splaytree_map/splaytree.c +370 -0
  15. data/lib/algorithms/search.rb +84 -0
  16. data/lib/algorithms/sort.rb +238 -0
  17. data/lib/algorithms.rb +67 -0
  18. data/lib/containers/deque.rb +171 -0
  19. data/lib/containers/heap.rb +486 -0
  20. data/lib/containers/kd_tree.rb +87 -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_tree_spec.rb +4 -0
  32. data/spec/priority_queue_spec.rb +75 -0
  33. data/spec/queue_spec.rb +61 -0
  34. data/spec/rb_tree_map_gc_mark_spec.rb +25 -0
  35. data/spec/rb_tree_map_spec.rb +123 -0
  36. data/spec/search_spec.rb +28 -0
  37. data/spec/sort_spec.rb +28 -0
  38. data/spec/splay_tree_map_spec.rb +102 -0
  39. data/spec/stack_spec.rb +60 -0
  40. data/spec/suffix_array_spec.rb +40 -0
  41. data/spec/trie_spec.rb +59 -0
  42. metadata +120 -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,370 @@
1
+ #include "ruby.h"
2
+
3
+ typedef struct struct_splaytree_node {
4
+ VALUE key;
5
+ VALUE value;
6
+ struct struct_splaytree_node *left;
7
+ struct struct_splaytree_node *right;
8
+ } splaytree_node;
9
+
10
+ typedef struct {
11
+ int (*compare_function)(VALUE key1, VALUE key2);
12
+ int size;
13
+ splaytree_node *root;
14
+ splaytree_node *header;
15
+ } splaytree;
16
+
17
+ static void recursively_free_nodes(splaytree_node *node) {
18
+ if(node) {
19
+ recursively_free_nodes(node->left);
20
+ recursively_free_nodes(node->right);
21
+ free(node);
22
+ }
23
+ return;
24
+ }
25
+
26
+ static splaytree* get_tree_from_self(VALUE self) {
27
+ splaytree *tree;
28
+ Data_Get_Struct(self, splaytree, tree);
29
+ return tree;
30
+ }
31
+
32
+ static void splay(splaytree *tree, VALUE key) {
33
+ int cmp, cmp2;
34
+ splaytree_node *l, *r, *t, *y;
35
+
36
+ l = tree->header;
37
+ r = tree->header;
38
+ t = tree->root;
39
+
40
+ tree->header->left = NULL;
41
+ tree->header->right = NULL;
42
+
43
+ while(1) {
44
+ cmp = tree->compare_function(key, t->key);
45
+ if (cmp == -1) {
46
+ if (!(t->left)) break;
47
+ cmp2 = tree->compare_function(key, t->left->key);
48
+ if (cmp2 == -1) {
49
+ y = t->left;
50
+ t->left = y->right;
51
+ y->right = t;
52
+ t = y;
53
+ if (!(t->left)) break;
54
+ }
55
+ r->left = t;
56
+ r = t;
57
+ t = t->left;
58
+ }
59
+ else if (cmp == 1) {
60
+ if (!(t->right)) break;
61
+ cmp2 = tree->compare_function(key, t->right->key);
62
+ if (cmp2 == 1) {
63
+ y = t->right;
64
+ t->right = y->left;
65
+ y->left = t;
66
+ t = y;
67
+ if (!(t->right)) break;
68
+ }
69
+ l->right = t;
70
+ l = t;
71
+ t = t->right;
72
+ } else {
73
+ break;
74
+ }
75
+ }
76
+ l->right = t->left;
77
+ r->left = t->right;
78
+ t->left = tree->header->right;
79
+ t->right = tree->header->left;
80
+ tree->root = t;
81
+ }
82
+
83
+ static int height(splaytree_node *h) {
84
+ int left_height, right_height;
85
+
86
+ if(!h) { return 0; }
87
+
88
+ left_height = 1 + height(h->left);
89
+ right_height = 1 + height(h->right);
90
+
91
+ return left_height > right_height ? left_height : right_height;
92
+ }
93
+
94
+ static splaytree* create_splaytree(int (*compare_function)(VALUE, VALUE)) {
95
+ splaytree *tree = ALLOC(splaytree);
96
+ tree->compare_function = compare_function;
97
+ tree->root = NULL;
98
+ tree->size = 0;
99
+ tree->header = ALLOC(splaytree_node);
100
+ return tree;
101
+ }
102
+
103
+ static splaytree_node* create_node(VALUE key, VALUE value) {
104
+ splaytree_node *new_node = ALLOC(splaytree_node);
105
+ new_node->key = key;
106
+ new_node->value = value;
107
+ new_node->left = NULL;
108
+ new_node->right = NULL;
109
+ return new_node;
110
+ }
111
+
112
+ static void insert(splaytree *tree, VALUE key, VALUE value) {
113
+ int cmp;
114
+ splaytree_node *new_node;
115
+
116
+ if (!(tree->root)) {
117
+ new_node = create_node(key, value);
118
+ tree->root = new_node;
119
+ tree->size += 1;
120
+ return;
121
+ }
122
+
123
+ splay(tree, key);
124
+ cmp = tree->compare_function(key, tree->root->key);
125
+ if (cmp == 0) {
126
+ tree->root->value = value;
127
+ return;
128
+ } else {
129
+ new_node = create_node(key, value);
130
+ if (cmp == -1) {
131
+ new_node->left = tree->root->left;
132
+ new_node->right = tree->root;
133
+ tree->root->left = NULL;
134
+ } else { /* cmp == 1 */
135
+ new_node->right = tree->root->right;
136
+ new_node->left = tree->root;
137
+ tree->root->right = NULL;
138
+ }
139
+ tree->root = new_node;
140
+ tree->size += 1;
141
+ }
142
+ }
143
+
144
+ static VALUE get(splaytree *tree, VALUE key) {
145
+ int cmp;
146
+ if (!tree->root)
147
+ return Qnil;
148
+
149
+ splay(tree, key);
150
+ cmp = tree->compare_function(key, tree->root->key);
151
+ if (cmp == 0) {
152
+ return tree->root->value;
153
+ }
154
+ return Qnil;
155
+ }
156
+
157
+ static VALUE delete(splaytree *tree, VALUE key) {
158
+ int cmp;
159
+ splaytree_node *x, *deleted_root;
160
+ VALUE deleted;
161
+
162
+ splay(tree, key);
163
+ cmp = tree->compare_function(key, tree->root->key);
164
+ if (cmp == 0) {
165
+ deleted = tree->root->value;
166
+ deleted_root = tree->root;
167
+ if (!(tree->root->left)) {
168
+ tree->root = tree->root->right;
169
+ } else {
170
+ x = tree->root->right;
171
+ tree->root = tree->root->left;
172
+ splay(tree, key);
173
+ tree->root->right = x;
174
+ }
175
+ free(deleted_root);
176
+ tree->size -= 1;
177
+ return deleted;
178
+ }
179
+ return Qnil;
180
+ }
181
+
182
+ static splaytree* splaytree_each_node(splaytree *tree, splaytree_node *node, void (*each)(splaytree *tree_, splaytree_node *node_, void* args), void* arguments) {
183
+ if (!node)
184
+ return NULL;
185
+
186
+ if (node->left)
187
+ splaytree_each_node(tree, node->left, each, arguments);
188
+
189
+ (*each)(tree, node, arguments);
190
+
191
+ if (node->right)
192
+ splaytree_each_node(tree, node->right, each, arguments);
193
+ return tree;
194
+ }
195
+
196
+ static splaytree* splay_each(splaytree *tree, void (*each)(splaytree *tree, splaytree_node *node, void *args), void* arguments) {
197
+ if (tree->root)
198
+ splaytree_each_node(tree, tree->root, each, arguments);
199
+ return tree;
200
+ }
201
+
202
+ // Methods to be called in Ruby
203
+
204
+ static int id_compare_operator;
205
+
206
+ static int splaytree_compare_function(VALUE a, VALUE b) {
207
+ if (a == b) return 0;
208
+ if (FIXNUM_P(a) && FIXNUM_P(b)) {
209
+ long x = FIX2LONG(a), y = FIX2LONG(b);
210
+ if (x == y) return 0;
211
+ if (x > y) return 1;
212
+ return -1;
213
+ }
214
+ if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString &&
215
+ TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) {
216
+ return rb_str_cmp(a, b);
217
+ }
218
+ return FIX2INT(rb_funcall((VALUE) a, id_compare_operator, 1, (VALUE) b));
219
+ }
220
+
221
+ static VALUE splaytree_init(VALUE self)
222
+ {
223
+ return self;
224
+ }
225
+
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
+ static void splaytree_mark(void *ptr) {
236
+ if (ptr) {
237
+ splaytree *tree = ptr;
238
+ recursively_mark_nodes(tree->root);
239
+ }
240
+ }
241
+
242
+ static void splaytree_free(void *ptr) {
243
+ if (ptr) {
244
+ splaytree *tree = ptr;
245
+ recursively_free_nodes(tree->root);
246
+ free(tree->header);
247
+ free(tree);
248
+ }
249
+ }
250
+
251
+ static VALUE splaytree_alloc(VALUE klass) {
252
+ splaytree *tree = create_splaytree(&splaytree_compare_function);
253
+ return Data_Wrap_Struct(klass, splaytree_mark, splaytree_free, tree);
254
+ }
255
+
256
+ static VALUE splaytree_push(VALUE self, VALUE key, VALUE value) {
257
+ splaytree *tree = get_tree_from_self(self);
258
+ insert(tree, key, value);
259
+ return value;
260
+ }
261
+
262
+ static VALUE splaytree_get(VALUE self, VALUE key) {
263
+ splaytree *tree = get_tree_from_self(self);
264
+ return get(tree, key);
265
+ }
266
+
267
+ static VALUE splaytree_size(VALUE self) {
268
+ splaytree *tree = get_tree_from_self(self);
269
+ return INT2NUM(tree->size);
270
+ }
271
+
272
+ static VALUE splaytree_is_empty(VALUE self) {
273
+ splaytree *tree = get_tree_from_self(self);
274
+ return (tree->root ? Qfalse : Qtrue);
275
+ }
276
+
277
+ static VALUE splaytree_height(VALUE self) {
278
+ splaytree *tree = get_tree_from_self(self);
279
+ return INT2NUM(height(tree->root));
280
+ }
281
+
282
+ static VALUE splaytree_has_key(VALUE self, VALUE key) {
283
+ splaytree *tree = get_tree_from_self(self);
284
+ if(!tree->root) { return Qfalse; }
285
+ if(get(tree, key) == Qnil)
286
+ return Qfalse;
287
+
288
+ return Qtrue;
289
+ }
290
+
291
+ static VALUE splaytree_min_key(VALUE self) {
292
+ splaytree *tree = get_tree_from_self(self);
293
+ splaytree_node *node;
294
+
295
+ if(!tree->root)
296
+ return Qnil;
297
+
298
+ node = tree->root;
299
+ while (node->left)
300
+ node = node->left;
301
+
302
+ return node->key;
303
+ }
304
+
305
+ static VALUE splaytree_max_key(VALUE self) {
306
+ splaytree *tree = get_tree_from_self(self);
307
+ splaytree_node *node;
308
+
309
+ if(!tree->root)
310
+ return Qnil;
311
+
312
+ node = tree->root;
313
+ while (node->right)
314
+ node = node->right;
315
+
316
+ return node->key;
317
+ }
318
+
319
+ static VALUE splaytree_delete(VALUE self, VALUE key) {
320
+ splaytree *tree = get_tree_from_self(self);
321
+ if(!tree->root)
322
+ return Qnil;
323
+
324
+ return delete(tree, key);
325
+ }
326
+
327
+ static VALUE splaytree_clear(VALUE self) {
328
+ splaytree *tree = get_tree_from_self(self);
329
+ recursively_free_nodes(tree->root);
330
+ tree->root = NULL;
331
+ tree->size = 0;
332
+
333
+ return Qnil;
334
+ }
335
+
336
+ static void splaytree_each_helper(splaytree *tree, splaytree_node *node, void *args) {
337
+ rb_yield(rb_ary_new3(2, node->key, node->value));
338
+ };
339
+
340
+ static VALUE splaytree_each(VALUE self) {
341
+ splaytree *tree = get_tree_from_self(self);
342
+ splay_each(tree, &splaytree_each_helper, NULL);
343
+ return self;
344
+ }
345
+
346
+ static VALUE CSplayTree;
347
+ static VALUE mContainers;
348
+
349
+ void Init_CSplayTreeMap() {
350
+ id_compare_operator = rb_intern("<=>");
351
+
352
+ mContainers = rb_define_module("Containers");
353
+ CSplayTree = rb_define_class_under(mContainers, "CSplayTreeMap", rb_cObject);
354
+ rb_define_alloc_func(CSplayTree, splaytree_alloc);
355
+ rb_define_method(CSplayTree, "initialize", splaytree_init, 0);
356
+ rb_define_method(CSplayTree, "push", splaytree_push, 2);
357
+ rb_define_method(CSplayTree, "clear", splaytree_clear, 0);
358
+ rb_define_alias(CSplayTree, "[]=", "push");
359
+ rb_define_method(CSplayTree, "size", splaytree_size, 0);
360
+ rb_define_method(CSplayTree, "empty?", splaytree_is_empty, 0);
361
+ rb_define_method(CSplayTree, "height", splaytree_height, 0);
362
+ rb_define_method(CSplayTree, "min_key", splaytree_min_key, 0);
363
+ rb_define_method(CSplayTree, "max_key", splaytree_max_key, 0);
364
+ rb_define_method(CSplayTree, "each", splaytree_each, 0);
365
+ rb_define_method(CSplayTree, "get", splaytree_get, 1);
366
+ rb_define_alias(CSplayTree, "[]", "get");
367
+ rb_define_method(CSplayTree, "has_key?", splaytree_has_key, 1);
368
+ rb_define_method(CSplayTree, "delete", splaytree_delete, 1);
369
+ rb_include_module(CSplayTree, rb_eval_string("Enumerable"));
370
+ }
@@ -0,0 +1,84 @@
1
+ =begin rdoc
2
+ This module implements search algorithms. Documentation is provided for each algorithm.
3
+
4
+ =end
5
+ module Algorithms::Search
6
+ # Binary Search: This search finds an item in log(n) time provided that the container is already sorted.
7
+ # The method returns the item if it is found, or nil if it is not. If there are duplicates, the first one
8
+ # found is returned, and this is not guaranteed to be the smallest or largest item.
9
+ #
10
+ # Complexity: O(lg N)
11
+ #
12
+ # Algorithms::Search.binary_search([1, 2, 3], 1) #=> 1
13
+ # Algorithms::Search.binary_search([1, 2, 3], 4) #=> nil
14
+ def self.binary_search(container, item)
15
+ return nil if item.nil?
16
+ low = 0
17
+ high = container.size - 1
18
+ while low <= high
19
+ mid = (low + high) / 2
20
+ val = container[mid]
21
+ if val > item
22
+ high = mid - 1
23
+ elsif val < item
24
+ low = mid + 1
25
+ else
26
+ return val
27
+ end
28
+ end
29
+ nil
30
+ end
31
+
32
+ # Knuth-Morris-Pratt Algorithm substring search algorithm: Efficiently finds the starting position of a
33
+ # substring in a string. The algorithm calculates the best position to resume searching from if a failure
34
+ # occurs.
35
+ #
36
+ # The method returns the index of the starting position in the string where the substring is found. If there
37
+ # is no match, nil is returned.
38
+ #
39
+ # Complexity: O(n + k), where n is the length of the string and k is the length of the substring.
40
+ #
41
+ # Algorithms::Search.kmp_search("ABC ABCDAB ABCDABCDABDE", "ABCDABD") #=> 15
42
+ # Algorithms::Search.kmp_search("ABC ABCDAB ABCDABCDABDE", "ABCDEF") #=> nil
43
+ def self.kmp_search(string, substring)
44
+ return nil if string.nil? or substring.nil?
45
+
46
+ # create failure function table
47
+ pos = 2
48
+ cnd = 0
49
+ failure_table = [-1, 0]
50
+ while pos < substring.length
51
+ if substring[pos - 1] == substring[cnd]
52
+ failure_table[pos] = cnd + 1
53
+ pos += 1
54
+ cnd += 1
55
+ elsif cnd > 0
56
+ cnd = failure_table[cnd]
57
+ else
58
+ failure_table[pos] = 0
59
+ pos += 1
60
+ end
61
+ end
62
+
63
+ m = i = 0
64
+ while m + i < string.length
65
+ if substring[i] == string[m + i]
66
+ i += 1
67
+ return m if i == substring.length
68
+ else
69
+ m = m + i - failure_table[i]
70
+ i = failure_table[i] if i > 0
71
+ end
72
+ end
73
+ return nil
74
+ end
75
+
76
+ # Allows kmp_search to be called as an instance method in classes that include the Search module.
77
+ #
78
+ # class String; include Algorithms::Search; end
79
+ # "ABC ABCDAB ABCDABCDABDE".kmp_search("ABCDABD") #=> 15
80
+ def kmp_search(substring)
81
+ Algorithms::Search.kmp_search(self, substring)
82
+ end
83
+
84
+ end