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.
- data/History.txt +23 -0
- data/Manifest +23 -0
- data/README.txt +58 -0
- data/Rakefile +17 -0
- data/algorithms.gemspec +105 -0
- data/benchmark.rb +49 -0
- data/ext/containers/priority_queue/extconf.rb +4 -0
- data/ext/containers/priority_queue/priority_queue.c +948 -0
- data/ext/containers/tree_map/Rakefile +4 -0
- data/ext/containers/tree_map/extconf.rb +4 -0
- data/ext/containers/tree_map/rbtree.c +395 -0
- data/lib/algorithms.rb +7 -0
- data/lib/containers/hash.rb +0 -0
- data/lib/containers/heap.rb +146 -0
- data/lib/containers/priority_queue.rb +514 -0
- data/lib/containers/queue.rb +29 -0
- data/lib/containers/stack.rb +29 -0
- data/lib/containers/tree_map.rb +265 -0
- data/spec/heap_spec.rb +74 -0
- data/spec/priority_queue_spec.rb +31 -0
- data/spec/priority_queue_test.rb +371 -0
- data/spec/queue_spec.rb +53 -0
- data/spec/stack_spec.rb +53 -0
- data/spec/tree_map_spec.rb +99 -0
- metadata +104 -0
@@ -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
|
+
}
|
data/lib/algorithms.rb
ADDED
@@ -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
|