algorithms 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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