algorithms 0.0.1

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.
@@ -0,0 +1,4 @@
1
+ task :default do
2
+ sh "make"
3
+ sh "ruby -e 'require \"c_tree_map\"; puts a = CTreeMap.new; 100.times { |x| a.put(x,x) }; p a.size; p a.get(13); p a.contains?(200)'"
4
+ end
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+ extension_name = "CTreeMap"
3
+ dir_config(extension_name)
4
+ create_makefile(extension_name)
@@ -0,0 +1,395 @@
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
+ void recursively_free_nodes(rbtree_node *node) {
26
+ if(node) {
27
+ recursively_free_nodes(node->left);
28
+ recursively_free_nodes(node->right);
29
+ free(node);
30
+ }
31
+ return;
32
+ }
33
+
34
+ static rbtree* get_tree_from_self(VALUE self) {
35
+ rbtree *tree;
36
+ Data_Get_Struct(self, rbtree, tree);
37
+ return tree;
38
+ }
39
+
40
+ int isred(rbtree_node *node) {
41
+ if(!node) { return FALSE; }
42
+
43
+ if(node->color == RED) { return TRUE; }
44
+ else return FALSE;
45
+ }
46
+
47
+ static void colorflip(rbtree_node *node) {
48
+ node->color = !node->color;
49
+ node->left->color = !node->left->color;
50
+ node->right->color = !node->right->color;
51
+ }
52
+
53
+ static int size(rbtree_node *h) {
54
+ if(!h) {
55
+ return 0;
56
+ }
57
+ else return h->num_nodes;
58
+ }
59
+
60
+ static int height(rbtree_node *h) {
61
+ if(!h) { return 0; }
62
+ else return h->height;
63
+ }
64
+
65
+ static rbtree_node* set_num_nodes(rbtree_node *h) {
66
+ h->num_nodes = size(h->left) + size(h->right) + 1;
67
+ if ( height(h->left) > height(h->right) ) {
68
+ h->height = height(h->left) +1;
69
+ }
70
+ else {
71
+ h->height = height(h->right) +1;
72
+ }
73
+ return h;
74
+ }
75
+
76
+ static rbtree_node* rotate_left(rbtree_node *h) {
77
+ rbtree_node *x = h->right;
78
+ h->right = x->left;
79
+ x->left = set_num_nodes(h);
80
+ x->color = x->left->color;
81
+ x->left->color = RED;
82
+ return set_num_nodes(x);
83
+ }
84
+
85
+ static rbtree_node* rotate_right(rbtree_node *h) {
86
+ rbtree_node *x = h->left;
87
+ h->left = x->right;
88
+ x->right = set_num_nodes(h);
89
+ x->color = x->right->color;
90
+ x->right->color = RED;
91
+ return set_num_nodes(x);
92
+ }
93
+
94
+ static rbtree_node* move_red_left(rbtree_node *h) {
95
+ colorflip(h);
96
+ if ( isred(h->right->left) ) {
97
+ h->right = rotate_right(h->right);
98
+ h = rotate_left(h);
99
+ colorflip(h);
100
+ }
101
+ return h;
102
+ }
103
+
104
+ static rbtree_node* move_red_right(rbtree_node *h) {
105
+ colorflip(h);
106
+ if ( isred(h->left->left) ) {
107
+ h = rotate_right(h);
108
+ colorflip(h);
109
+ }
110
+ return h;
111
+ }
112
+
113
+ static rbtree_node* fixup(rbtree_node *h) {
114
+ if ( isred(h->right) )
115
+ h = rotate_left(h);
116
+
117
+ if ( isred(h->left) && isred(h->left->left) )
118
+ h = rotate_right(h);
119
+
120
+ if ( isred(h->left) && isred(h->right) )
121
+ colorflip(h);
122
+
123
+ return set_num_nodes(h);
124
+ }
125
+ static rbtree* create_rbtree(int (*compare_function)(VALUE, VALUE)) {
126
+ rbtree *tree = ALLOC(rbtree);
127
+ tree->black_height = 0;
128
+ tree->compare_function = compare_function;
129
+ tree->root = NULL;
130
+ return tree;
131
+ }
132
+
133
+ static rbtree_node* insert(rbtree *tree, rbtree_node *node, VALUE key, VALUE value) {
134
+ int cmp;
135
+
136
+ // This slot is empty, so we insert our new node
137
+ if(!node) {
138
+ rbtree_node *new_node = ALLOC(rbtree_node);
139
+ new_node->key = key;
140
+ new_node->value = value;
141
+ new_node->color = RED;
142
+ new_node->height = 1;
143
+ new_node->num_nodes = 1;
144
+ new_node->left = NULL;
145
+ new_node->right = NULL;
146
+ return new_node;
147
+ }
148
+
149
+ // Do a top-down breaking of 4-nodes
150
+ if ( isred(node->left) && isred(node->right) ) {
151
+ colorflip(node);
152
+ }
153
+
154
+ // Insert left or right, recursively
155
+ cmp = tree->compare_function(key, node->key);
156
+ if (cmp == 0) { node->value = value; }
157
+ else if (cmp == -1) { node->left = insert(tree, node->left, key, value); }
158
+ else { node->right = insert(tree, node->right, key, value); }
159
+
160
+ // Fix our tree to keep left-lean
161
+ if (isred(node->right)) { node = rotate_left(node); }
162
+ if (isred(node->left) && isred(node->left->left)) { node = rotate_right(node); }
163
+
164
+ return set_num_nodes(node);
165
+ }
166
+
167
+ static VALUE get(rbtree *tree, rbtree_node *node, VALUE key) {
168
+ int cmp;
169
+ if (!node) {
170
+ return Qnil;
171
+ }
172
+
173
+ cmp = tree->compare_function(key, node->key);
174
+ if (cmp == 0) { return node->value; }
175
+ else if (cmp == -1) { return get(tree, node->left, key); }
176
+ else { return get(tree, node->right, key); }
177
+
178
+ }
179
+
180
+ static VALUE min_key(rbtree_node *node) {
181
+ if (!node->left)
182
+ return node->key;
183
+
184
+ return min_key(node->left);
185
+ }
186
+
187
+ static VALUE max_key(rbtree_node *node) {
188
+ if (!node->right)
189
+ return node->key;
190
+
191
+ return max_key(node->right);
192
+ }
193
+
194
+ static rbtree_node* delete_min(rbtree_node *h) {
195
+ if ( !(h->left) )
196
+ return NULL;
197
+
198
+ if ( !isred(h->left) && !isred(h->left->left) )
199
+ h = move_red_left(h);
200
+
201
+ h->left = delete_min(h->left);
202
+
203
+ return fixup(h);
204
+ }
205
+
206
+ static rbtree_node* delete_max(rbtree_node *h) {
207
+ if ( isred(h->left) )
208
+ h = rotate_right(h);
209
+
210
+ if ( !(h->right) )
211
+ return NULL;
212
+
213
+ if ( !isred(h->right) && !isred(h->right->left) )
214
+ h = move_red_right(h);
215
+
216
+ h->right = delete_max(h->right);
217
+
218
+ return fixup(h);
219
+ }
220
+
221
+
222
+ static rbtree_node* delete(rbtree *tree, rbtree_node *node, VALUE key, VALUE *deleted_value) {
223
+ int cmp;
224
+ VALUE minimum_key;
225
+ cmp = tree->compare_function(key, node->key);
226
+ if (cmp == -1) {
227
+ if ( !isred(node->left) && !isred(node->left->left) )
228
+ node = move_red_left(node);
229
+
230
+ node->left = delete(tree, node->left, key, deleted_value);
231
+ }
232
+ else {
233
+ if ( isred(node->left) )
234
+ node = rotate_right(node);
235
+
236
+ if ( (cmp == 0) && !(node->right) ) {
237
+ *deleted_value = node->value;
238
+ return NULL;
239
+ }
240
+
241
+ if ( !isred(node->right) && !isred(node->right->left) )
242
+ node = move_red_right(node);
243
+
244
+ cmp = tree->compare_function(key, node->key);
245
+ if (cmp == 0) {
246
+ *deleted_value = node->value;
247
+ minimum_key = min_key(node->right);
248
+ node->value = get(tree, node->right, minimum_key);
249
+ node->key = minimum_key;
250
+ node->right = delete_min(node->right);
251
+ }
252
+ else {
253
+ node->right = delete(tree, node->right, key, deleted_value);
254
+ }
255
+ }
256
+ return fixup(node);
257
+ }
258
+
259
+ static rbtree* rbtree_each_node(rbtree *tree, rbtree_node *node, void (*each)(rbtree *tree_, rbtree_node *node_, void* args), void* arguments) {
260
+ if (!node)
261
+ return NULL;
262
+
263
+ if (node->left)
264
+ rbtree_each_node(tree, node->left, each, arguments);
265
+ (*each)(tree, node, arguments);
266
+ if (node->right)
267
+ rbtree_each_node(tree, node->right, each, arguments);
268
+ return tree;
269
+ }
270
+
271
+ static rbtree* rbt_each(rbtree *tree, void (*each)(rbtree *tree, rbtree_node *node, void *args), void* arguments) {
272
+ if (tree->root)
273
+ rbtree_each_node(tree, tree->root, each, arguments);
274
+ return tree;
275
+ }
276
+
277
+
278
+ // Methods to be called in Ruby
279
+
280
+ static int id_compare_operator;
281
+
282
+ static int rbtree_compare_function(VALUE a, VALUE b) {
283
+ return FIX2INT(rb_funcall((VALUE) a, id_compare_operator, 1, (VALUE) b));
284
+ }
285
+
286
+ static VALUE rbtree_init(VALUE self)
287
+ {
288
+ return self;
289
+ }
290
+
291
+ static void rbtree_free(rbtree *tree) {
292
+ recursively_free_nodes(tree->root);
293
+ free(tree);
294
+ }
295
+
296
+ static VALUE rbtree_alloc(VALUE klass) {
297
+ rbtree *tree = create_rbtree(&rbtree_compare_function);
298
+ return Data_Wrap_Struct(klass, NULL, rbtree_free, tree);
299
+ }
300
+
301
+ static VALUE rbtree_put(VALUE self, VALUE key, VALUE value) {
302
+ rbtree *tree = get_tree_from_self(self);
303
+ tree->root = insert(tree, tree->root, key, value);
304
+ return value;
305
+ }
306
+
307
+ static VALUE rbtree_get(VALUE self, VALUE key) {
308
+ rbtree *tree = get_tree_from_self(self);
309
+ return get(tree, tree->root, key);
310
+ }
311
+
312
+ static VALUE rbtree_size(VALUE self) {
313
+ rbtree *tree = get_tree_from_self(self);
314
+ return INT2NUM(size(tree->root));
315
+ }
316
+
317
+ static VALUE rbtree_height(VALUE self) {
318
+ rbtree *tree = get_tree_from_self(self);
319
+ return INT2NUM(height(tree->root));
320
+ }
321
+
322
+ static VALUE rbtree_contains(VALUE self, VALUE key) {
323
+ rbtree *tree = get_tree_from_self(self);
324
+ if(get(tree, tree->root, key) == Qnil)
325
+ return Qfalse;
326
+
327
+ return Qtrue;
328
+ }
329
+
330
+ static VALUE rbtree_min_key(VALUE self) {
331
+ rbtree *tree = get_tree_from_self(self);
332
+ if(!tree->root)
333
+ return Qnil;
334
+
335
+ return min_key(tree->root);
336
+ }
337
+
338
+ static VALUE rbtree_max_key(VALUE self) {
339
+ rbtree *tree = get_tree_from_self(self);
340
+ if(!tree->root)
341
+ return Qnil;
342
+
343
+ return max_key(tree->root);
344
+ }
345
+
346
+ static VALUE rbtree_delete(VALUE self, VALUE key) {
347
+ VALUE deleted_value;
348
+ rbtree *tree = get_tree_from_self(self);
349
+ if(!tree->root)
350
+ return Qnil;
351
+
352
+ tree->root = delete(tree, tree->root, key, &deleted_value);
353
+ if(!tree->root)
354
+ tree->root->color = BLACK;
355
+
356
+ if(deleted_value) {
357
+ return deleted_value;
358
+ }
359
+
360
+ return Qnil;
361
+ }
362
+
363
+ static void rbtree_each_helper(rbtree *tree, rbtree_node *node, void *args) {
364
+ rb_yield(rb_ary_new3(2, node->key, node->value));
365
+ };
366
+
367
+ static VALUE rbtree_each(VALUE self) {
368
+ rbtree *tree = get_tree_from_self(self);
369
+ rbt_each(tree, &rbtree_each_helper, NULL);
370
+ return self;
371
+ }
372
+
373
+ static VALUE cRBTree;
374
+ static VALUE mContainers;
375
+
376
+ void Init_CTreeMap() {
377
+ id_compare_operator = rb_intern("<=>");
378
+
379
+ mContainers = rb_define_module("Containers");
380
+ cRBTree = rb_define_class_under(mContainers, "CTreeMap", rb_cObject);
381
+ rb_define_alloc_func(cRBTree, rbtree_alloc);
382
+ rb_define_method(cRBTree, "initialize", rbtree_init, 0);
383
+ rb_define_method(cRBTree, "put", rbtree_put, 2);
384
+ rb_define_alias(cRBTree, "[]=", "put");
385
+ rb_define_method(cRBTree, "size", rbtree_size, 0);
386
+ rb_define_method(cRBTree, "height", rbtree_height, 0);
387
+ rb_define_method(cRBTree, "min_key", rbtree_min_key, 0);
388
+ rb_define_method(cRBTree, "max_key", rbtree_max_key, 0);
389
+ rb_define_method(cRBTree, "each", rbtree_each, 0);
390
+ rb_define_method(cRBTree, "get", rbtree_get, 1);
391
+ rb_define_alias(cRBTree, "[]", "get");
392
+ rb_define_method(cRBTree, "contains?", rbtree_contains, 1);
393
+ rb_define_method(cRBTree, "delete", rbtree_delete, 1);
394
+ rb_include_module(cRBTree, rb_eval_string("Enumerable"));
395
+ }
@@ -0,0 +1,7 @@
1
+ %w(heap stack queue priority_queue tree_map).each { |file| require "#{File.dirname(__FILE__)}/containers/#{file}" }
2
+ begin
3
+ require 'CTreeMap'
4
+ Containers::TreeMap = Containers::CTreeMap
5
+ rescue LoadError # C Version could not be found, try ruby version
6
+ Containers::TreeMap = Containers::RubyTreeMap
7
+ end
File without changes
@@ -0,0 +1,146 @@
1
+ module Containers
2
+ # Implemented as a Binomial heap
3
+ class Heap
4
+ class Node
5
+ attr_accessor :object, :left, :right
6
+ def initialize(object)
7
+ @left = nil
8
+ @right = nil
9
+ @object = object
10
+ end
11
+
12
+ end
13
+
14
+ attr_reader :root_array
15
+
16
+ def initialize(ary=[], &block)
17
+ @compare_function = block_given? ? block : lambda { |x, y| (x <=> y) == -1 }
18
+ @root_array = []
19
+ @size = 0
20
+ if !ary.empty?
21
+ ary.each { |n| insert(n) }
22
+ end
23
+ end
24
+
25
+ def size
26
+ @size
27
+ end
28
+
29
+ def peek
30
+ return nil if @size < 1
31
+ next_index, next_object = -1, nil
32
+
33
+ @root_array.size.times do |i|
34
+ unless @root_array[i].nil?
35
+ if ((next_index == -1) || @compare_function.call(next_object, @root_array[i].object))
36
+ next_index, next_object = i, @root_array[i].object
37
+ end
38
+ end
39
+ end
40
+ return next_object
41
+ end
42
+
43
+ def get_next!
44
+ return nil if @size < 1
45
+ next_index, next_object = -1, nil
46
+
47
+ # Remove the root node containing the maximum from its power-of-2 heap
48
+ @root_array.size.times do |i|
49
+ unless @root_array[i].nil?
50
+ if ((next_index == -1) || @compare_function.call(next_object, @root_array[i].object))
51
+ next_index, next_object = i, @root_array[i].object
52
+ end
53
+ end
54
+ end
55
+
56
+ # Temporarily build a binomial queue containing the remaining parts of the power-of-2 heap, and merge this back into the original
57
+ temp = []
58
+ x = @root_array[next_index].left
59
+ (next_index-1).downto(0) do |i|
60
+ temp[i] = x
61
+ x = x.right
62
+ temp[i].right = nil
63
+ end
64
+
65
+ @root_array[next_index] = nil
66
+ merge!(temp)
67
+ @size -= 1
68
+ return next_object
69
+ end
70
+
71
+ def insert(object)
72
+ c = Node.new(object)
73
+ (0..@root_array.size+1).each do |i|
74
+ break if c.nil?
75
+ if @root_array[i].nil? # The spot is empty, so we use it
76
+ @root_array[i] = c
77
+ break
78
+ end
79
+ c = pair(c, @root_array[i]) # Otherwise, join the two and proceed
80
+ @root_array[i] = nil
81
+ end
82
+ @size += 1
83
+ return object
84
+ end
85
+
86
+ def merge!(otherheap)
87
+ if (otherheap.class == Containers::Heap || otherheap.class == Containers::MinHeap || otherheap.class == Containers::MaxHeap)
88
+ othersize = otherheap.size
89
+ otherheap = otherheap.root_array
90
+ end
91
+ a, b, c = @root_array, otherheap, nil
92
+ if(a.size < b.size) # Make sure 'a' is always bigger
93
+ a, b = b, a
94
+ end
95
+
96
+ (0..b.size).each do |i|
97
+ case bits(c, b[i], a[i])
98
+ when 2 then a[i] = b[i]
99
+ when 3 then c = pair(a[i], b[i]); a[i] = nil
100
+ when 4 then a[i] = c; c = nil
101
+ when 5 then c = pair(c, a[i]); a[i] = nil
102
+ when 6..7 then c = pair(c, b[i])
103
+ end
104
+ end
105
+ @root_array = a
106
+ @size += othersize if othersize
107
+ end
108
+
109
+ private
110
+ def bits(c, b, a)
111
+ 4*(c.nil? ? 0 : 1) + 2*(b.nil? ? 0 : 1) + (a.nil? ? 0 : 1)
112
+ end
113
+
114
+ def pair(p, q)
115
+ if @compare_function.call(p.object, q.object)
116
+ p.right = q.left
117
+ q.left = p
118
+ return q
119
+ else
120
+ q.right = p.left
121
+ p.left = q
122
+ return p
123
+ end
124
+ end
125
+ end
126
+
127
+ class MaxHeap < Heap
128
+ def initialize(ary=[])
129
+ super(ary) { |x, y| (x <=> y) == -1 }
130
+ end
131
+
132
+ def get_max!
133
+ get_next!
134
+ end
135
+ end
136
+
137
+ class MinHeap < Heap
138
+ def initialize(ary=[])
139
+ super(ary) { |x, y| (x <=> y) == 1 }
140
+ end
141
+
142
+ def get_min!
143
+ get_next!
144
+ end
145
+ end
146
+ end