rbtree 0.2.0 → 0.2.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/ChangeLog +119 -61
- data/LICENSE +1 -1
- data/README +54 -26
- data/extconf.rb +4 -27
- data/rbtree.c +117 -138
- data/test.rb +110 -66
- metadata +45 -35
data/LICENSE
CHANGED
data/README
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
= Ruby/RBTree
|
4
4
|
|
5
|
-
RBTree is a sorted associative collection
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
RBTree is a sorted associative collection that is implemented with
|
6
|
+
Red-Black Tree. The elements of RBTree are ordered and its interface
|
7
|
+
is the almost same as Hash, so simply you can consider RBTree sorted
|
8
|
+
Hash.
|
9
9
|
|
10
10
|
Red-Black Tree is a kind of binary tree that automatically balances
|
11
11
|
by itself when a node is inserted or deleted. Thus the complexity
|
@@ -14,28 +14,48 @@ case. On the other hand the complexity of Hash is O(1). Because
|
|
14
14
|
Hash is unordered the data structure is more effective than
|
15
15
|
Red-Black Tree as an associative collection.
|
16
16
|
|
17
|
-
The
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
17
|
+
The elements of RBTree are sorted with natural ordering (by <=>
|
18
|
+
method) of its keys or by a comparator(Proc) set by readjust
|
19
|
+
method. It means all keys in RBTree should be comparable with each
|
20
|
+
other. Or a comparator that takes two arguments of a key should return
|
21
|
+
negative, 0, or positive depending on the first argument is less than,
|
22
|
+
equal to, or greater than the second one.
|
23
|
+
|
24
|
+
The interface of RBTree is the almost same as Hash and there are a
|
25
|
+
few methods to take advantage of the ordering:
|
26
|
+
|
27
|
+
* lower_bound, upper_bound, bound
|
28
|
+
* first, last
|
29
|
+
* shift, pop
|
30
|
+
* reverse_each
|
31
|
+
|
32
|
+
Note: while iterating RBTree (e.g. in a block of each method), it is
|
33
|
+
not modifiable, or TypeError is thrown.
|
34
|
+
|
35
|
+
RBTree supoorts pretty printing using pp.
|
36
|
+
|
37
|
+
This library contains two classes. One is RBTree and the other is
|
38
|
+
MultiRBTree that is a parent class of RBTree. RBTree does not allow
|
39
|
+
duplications of keys but MultiRBTree does.
|
40
|
+
|
41
|
+
require "rbtree"
|
42
|
+
|
43
|
+
rbtree = RBTree["c", 10, "a", 20]
|
44
|
+
rbtree["b"] = 30
|
45
|
+
p rbtree["b"] # => 30
|
46
|
+
rbtree.each do |k, v|
|
47
|
+
p [k, v]
|
48
|
+
end # => ["a", 20] ["b", 30] ["c", 10]
|
49
|
+
|
50
|
+
mrbtree = MultiRBTree["c", 10, "a", 20, "e", 30, "a", 40]
|
51
|
+
p mrbtree.lower_bound("b") # => ["c", 10]
|
52
|
+
mrbtree.bound("a", "d") do |k, v|
|
53
|
+
p [k, v]
|
54
|
+
end # => ["a", 20] ["a", 40] ["c", 10]
|
35
55
|
|
36
56
|
== Requirement
|
37
57
|
|
38
|
-
* Ruby 1.
|
58
|
+
* Ruby 1.8.x
|
39
59
|
|
40
60
|
== Install
|
41
61
|
|
@@ -43,7 +63,7 @@ MultiRBTree that allows duplicates of keys is also available.
|
|
43
63
|
|
44
64
|
or download a tarball from the link below
|
45
65
|
|
46
|
-
* ((<"Ruby/RBTree 0.2.
|
66
|
+
* ((<"Ruby/RBTree 0.2.1"|URL:rbtree-0.2.1.tar.gz>))
|
47
67
|
|
48
68
|
and then
|
49
69
|
|
@@ -57,13 +77,15 @@ and then
|
|
57
77
|
|
58
78
|
$ ruby test.rb
|
59
79
|
|
60
|
-
== Incomplete
|
80
|
+
== Incomplete Documents
|
61
81
|
|
62
82
|
$ rdoc rbtree.c
|
63
83
|
|
84
|
+
or online documents at ((<URL:http://rbtree.rubyforge.org/>)).
|
85
|
+
|
64
86
|
== License
|
65
87
|
|
66
|
-
MIT License. Copyright (c) 2002-2004, 2007 OZAWA Takuma.
|
88
|
+
MIT License. Copyright (c) 2002-2004, 2007, 2009 OZAWA Takuma.
|
67
89
|
|
68
90
|
dict.c and dict.h are modified copies that are originally in Kazlib
|
69
91
|
written by Kaz Kylheku. Copyright is held by Kaz Kylheku, see dict.c
|
@@ -75,4 +97,10 @@ and dict.h for the license. The web page of Kazlib is at
|
|
75
97
|
Bug fixes, suggestions and other feedbacks are welcomed. Please mail
|
76
98
|
me at burningdowntheopera at yahoo dot co dot jp.
|
77
99
|
|
100
|
+
== Links
|
101
|
+
|
102
|
+
* ((<RAA - ruby-rbtree|URL:http://raa.ruby-lang.org/project/ruby-rbtree/>))
|
103
|
+
* ((<RubyForge: rbtree: Project Info|URL:http://rubyforge.org/projects/rbtree/>))
|
104
|
+
* ((<URL:http://www.geocities.co.jp/SiliconValley-PaloAlto/3388/rbtree/README.html>))
|
105
|
+
|
78
106
|
=end
|
data/extconf.rb
CHANGED
@@ -1,34 +1,11 @@
|
|
1
1
|
require 'mkmf'
|
2
|
-
require 'rbconfig'
|
3
2
|
|
4
|
-
if
|
3
|
+
if $DEBUG
|
5
4
|
$CFLAGS << ' -std=c89 -pedantic -Wall -Wno-long-long'
|
6
|
-
|
7
|
-
|
8
|
-
$defs << '-DNDEBUG'
|
9
|
-
|
10
|
-
print 'checking for allocation framework... '
|
11
|
-
if Object.respond_to?(:allocate)
|
12
|
-
print "yes\n"
|
13
|
-
$defs << '-DHAVE_OBJECT_ALLOCATE'
|
5
|
+
$defs << ' -Dinline=__inline'
|
14
6
|
else
|
15
|
-
|
7
|
+
$defs << '-DNDEBUG'
|
16
8
|
end
|
17
9
|
|
18
|
-
have_func('
|
19
|
-
have_func('rb_block_proc')
|
20
|
-
have_func('rb_yield_values')
|
21
|
-
have_func('rb_marshal_dump')
|
22
|
-
have_func('rb_marshal_load')
|
23
|
-
|
24
|
-
print 'checking for inline keyword... '
|
25
|
-
inline = ['inline', '__inline', '__inline__', ''].find {|e|
|
26
|
-
try_link(<<EOS)
|
27
|
-
int main() { return 0; }
|
28
|
-
#{e} void foo() {}
|
29
|
-
EOS
|
30
|
-
}
|
31
|
-
print "#{inline}\n"
|
32
|
-
$defs << "-Dinline=#{inline}"
|
33
|
-
|
10
|
+
have_func('rb_enumeratorize')
|
34
11
|
create_makefile('rbtree')
|
data/rbtree.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* MIT License
|
3
|
-
* Copyright (c) 2002-2004, 2007 OZAWA Takuma
|
3
|
+
* Copyright (c) 2002-2004, 2007, 2009 OZAWA Takuma
|
4
4
|
*/
|
5
5
|
#include <ruby.h>
|
6
6
|
#include <version.h>
|
@@ -8,12 +8,11 @@
|
|
8
8
|
#include <stdarg.h>
|
9
9
|
#include "dict.h"
|
10
10
|
|
11
|
-
#define RBTREE_IN_ITERATION FL_USER1
|
12
11
|
#define RBTREE_PROC_DEFAULT FL_USER2
|
13
12
|
#define HASH_PROC_DEFAULT FL_USER2
|
14
13
|
|
15
|
-
#ifndef
|
16
|
-
#define
|
14
|
+
#ifndef HAVE_RB_ENUMERATORIZE
|
15
|
+
#define RETURN_ENUMERATOR(obj, argc, argv) ((void)0)
|
17
16
|
#endif
|
18
17
|
|
19
18
|
VALUE RBTree;
|
@@ -24,12 +23,6 @@ static ID id_cmp;
|
|
24
23
|
static ID id_call;
|
25
24
|
static ID id_default;
|
26
25
|
|
27
|
-
#ifndef HAVE_RB_MARSHAL_DUMP
|
28
|
-
static VALUE rb_mMarshal;
|
29
|
-
static ID id_dump;
|
30
|
-
static ID id_load;
|
31
|
-
#endif
|
32
|
-
|
33
26
|
typedef struct {
|
34
27
|
dict_t* dict;
|
35
28
|
VALUE ifnone;
|
@@ -51,41 +44,12 @@ typedef struct {
|
|
51
44
|
|
52
45
|
/*********************************************************************/
|
53
46
|
|
54
|
-
#ifndef HAVE_RB_BLOCK_PROC
|
55
|
-
static VALUE
|
56
|
-
rb_block_proc()
|
57
|
-
{
|
58
|
-
return rb_f_lambda();
|
59
|
-
}
|
60
|
-
#endif
|
61
|
-
|
62
|
-
#ifndef HAVE_RB_YIELD_VALUES
|
63
|
-
static VALUE
|
64
|
-
rb_yield_values(int n, ...)
|
65
|
-
{
|
66
|
-
int i;
|
67
|
-
va_list ap;
|
68
|
-
VALUE ary = rb_ary_new2(n);
|
69
|
-
|
70
|
-
va_start(ap, n);
|
71
|
-
for (i = 0; i < n; i++)
|
72
|
-
rb_ary_push(ary, va_arg(ap, VALUE));
|
73
|
-
va_end(ap);
|
74
|
-
return rb_yield(ary);
|
75
|
-
}
|
76
|
-
#endif
|
77
|
-
|
78
47
|
static int
|
79
48
|
cmpint(VALUE i, VALUE a, VALUE b)
|
80
49
|
{
|
81
|
-
#if RUBY_VERSION_CODE >= 180
|
82
50
|
return rb_cmpint(i, a, b);
|
83
|
-
#else
|
84
|
-
return rb_cmpint(i);
|
85
|
-
#endif
|
86
51
|
}
|
87
52
|
|
88
|
-
|
89
53
|
static void
|
90
54
|
rbtree_free(rbtree_t* rbtree)
|
91
55
|
{
|
@@ -187,19 +151,6 @@ VALUE rbtree_update(VALUE, VALUE);
|
|
187
151
|
|
188
152
|
/*********************************************************************/
|
189
153
|
|
190
|
-
#ifndef HAVE_OBJECT_ALLOCATE
|
191
|
-
/*
|
192
|
-
*
|
193
|
-
*/
|
194
|
-
VALUE
|
195
|
-
rbtree_s_new(int argc, VALUE* argv, VALUE klass)
|
196
|
-
{
|
197
|
-
VALUE rbtree = rbtree_alloc(klass);
|
198
|
-
rb_obj_call_init(rbtree, argc, argv);
|
199
|
-
return rbtree;
|
200
|
-
}
|
201
|
-
#endif
|
202
|
-
|
203
154
|
static int
|
204
155
|
hash_to_rbtree_i(VALUE key, VALUE value, VALUE rbtree)
|
205
156
|
{
|
@@ -214,17 +165,48 @@ hash_to_rbtree_i(VALUE key, VALUE value, VALUE rbtree)
|
|
214
165
|
VALUE
|
215
166
|
rbtree_s_create(int argc, VALUE* argv, VALUE klass)
|
216
167
|
{
|
217
|
-
|
168
|
+
long i;
|
218
169
|
VALUE rbtree;
|
219
|
-
|
170
|
+
|
220
171
|
if (argc == 1) {
|
172
|
+
VALUE tmp;
|
173
|
+
|
174
|
+
if (klass == RBTree && CLASS_OF(argv[0]) == MultiRBTree) {
|
175
|
+
rb_raise(rb_eTypeError, "can't convert MultiRBTree to RBTree");
|
176
|
+
}
|
177
|
+
|
221
178
|
if (rb_obj_is_kind_of(argv[0], klass)) {
|
222
179
|
rbtree = rbtree_alloc(klass);
|
223
180
|
rbtree_update(rbtree, argv[0]);
|
224
181
|
return rbtree;
|
225
|
-
}
|
182
|
+
}
|
183
|
+
|
184
|
+
tmp = rb_check_convert_type(argv[0], T_HASH, "Hash", "to_hash");
|
185
|
+
if (!NIL_P(tmp)) {
|
186
|
+
rbtree = rbtree_alloc(klass);
|
187
|
+
st_foreach(RHASH(tmp)->tbl, hash_to_rbtree_i, rbtree);
|
188
|
+
return rbtree;
|
189
|
+
}
|
190
|
+
|
191
|
+
tmp = rb_check_array_type(argv[0]);
|
192
|
+
if (!NIL_P(tmp)) {
|
226
193
|
rbtree = rbtree_alloc(klass);
|
227
|
-
|
194
|
+
for (i = 0; i < RARRAY(tmp)->len; i++) {
|
195
|
+
VALUE v = rb_check_array_type(RARRAY(tmp)->ptr[i]);
|
196
|
+
if (NIL_P(v)) {
|
197
|
+
continue;
|
198
|
+
}
|
199
|
+
switch(RARRAY(v)->len) {
|
200
|
+
case 1:
|
201
|
+
rbtree_aset(rbtree, RARRAY(v)->ptr[0], Qnil);
|
202
|
+
break;
|
203
|
+
case 2:
|
204
|
+
rbtree_aset(rbtree, RARRAY(v)->ptr[0], RARRAY(v)->ptr[1]);
|
205
|
+
break;
|
206
|
+
default:
|
207
|
+
continue;
|
208
|
+
}
|
209
|
+
}
|
228
210
|
return rbtree;
|
229
211
|
}
|
230
212
|
}
|
@@ -556,6 +538,7 @@ each_i(dnode_t* node, void* arg)
|
|
556
538
|
VALUE
|
557
539
|
rbtree_each(VALUE self)
|
558
540
|
{
|
541
|
+
RETURN_ENUMERATOR(self, 0, NULL);
|
559
542
|
return rbtree_for_each(self, each_i, NULL);
|
560
543
|
}
|
561
544
|
|
@@ -576,6 +559,7 @@ each_pair_i(dnode_t* node, void* arg)
|
|
576
559
|
VALUE
|
577
560
|
rbtree_each_pair(VALUE self)
|
578
561
|
{
|
562
|
+
RETURN_ENUMERATOR(self, 0, NULL);
|
579
563
|
return rbtree_for_each(self, each_pair_i, NULL);
|
580
564
|
}
|
581
565
|
|
@@ -596,6 +580,7 @@ each_key_i(dnode_t* node, void* arg)
|
|
596
580
|
VALUE
|
597
581
|
rbtree_each_key(VALUE self)
|
598
582
|
{
|
583
|
+
RETURN_ENUMERATOR(self, 0, NULL);
|
599
584
|
return rbtree_for_each(self, each_key_i, NULL);
|
600
585
|
}
|
601
586
|
|
@@ -616,6 +601,7 @@ each_value_i(dnode_t* node, void* arg)
|
|
616
601
|
VALUE
|
617
602
|
rbtree_each_value(VALUE self)
|
618
603
|
{
|
604
|
+
RETURN_ENUMERATOR(self, 0, NULL);
|
619
605
|
return rbtree_for_each(self, each_value_i, NULL);
|
620
606
|
}
|
621
607
|
|
@@ -629,6 +615,7 @@ rbtree_each_value(VALUE self)
|
|
629
615
|
VALUE
|
630
616
|
rbtree_reverse_each(VALUE self)
|
631
617
|
{
|
618
|
+
RETURN_ENUMERATOR(self, 0, NULL);
|
632
619
|
return rbtree_reverse_for_each(self, each_pair_i, NULL);
|
633
620
|
}
|
634
621
|
|
@@ -679,26 +666,13 @@ rbtree_initialize_copy(VALUE self, VALUE other)
|
|
679
666
|
return self;
|
680
667
|
}
|
681
668
|
|
682
|
-
#ifndef HAVE_RB_OBJ_INIT_COPY
|
683
|
-
/*
|
684
|
-
*
|
685
|
-
*/
|
686
|
-
VALUE
|
687
|
-
rbtree_clone(VALUE self)
|
688
|
-
{
|
689
|
-
VALUE clone = rbtree_alloc(CLASS_OF(self));
|
690
|
-
rbtree_initialize_copy(clone, self);
|
691
|
-
return clone;
|
692
|
-
}
|
693
|
-
#endif
|
694
|
-
|
695
669
|
/*
|
696
670
|
*
|
697
671
|
*/
|
698
672
|
VALUE
|
699
673
|
rbtree_values_at(int argc, VALUE* argv, VALUE self)
|
700
674
|
{
|
701
|
-
|
675
|
+
long i;
|
702
676
|
VALUE ary = rb_ary_new();
|
703
677
|
|
704
678
|
for (i = 0; i < argc; i++)
|
@@ -720,7 +694,10 @@ select_i(dnode_t* node, void* ary)
|
|
720
694
|
VALUE
|
721
695
|
rbtree_select(VALUE self)
|
722
696
|
{
|
723
|
-
VALUE ary
|
697
|
+
VALUE ary;
|
698
|
+
|
699
|
+
RETURN_ENUMERATOR(self, 0, NULL);
|
700
|
+
ary = rb_ary_new();
|
724
701
|
rbtree_for_each(self, select_i, (void*)ary);
|
725
702
|
return ary;
|
726
703
|
}
|
@@ -843,7 +820,8 @@ VALUE
|
|
843
820
|
rbtree_delete_if(VALUE self)
|
844
821
|
{
|
845
822
|
rbtree_delete_if_arg_t arg;
|
846
|
-
|
823
|
+
|
824
|
+
RETURN_ENUMERATOR(self, 0, NULL);
|
847
825
|
rbtree_modify(self);
|
848
826
|
arg.self = self;
|
849
827
|
arg.list = NULL;
|
@@ -857,7 +835,10 @@ rbtree_delete_if(VALUE self)
|
|
857
835
|
VALUE
|
858
836
|
rbtree_reject_bang(VALUE self)
|
859
837
|
{
|
860
|
-
|
838
|
+
dictcount_t count;
|
839
|
+
|
840
|
+
RETURN_ENUMERATOR(self, 0, NULL);
|
841
|
+
count = dict_count(DICT(self));
|
861
842
|
rbtree_delete_if(self);
|
862
843
|
if (count == dict_count(DICT(self)))
|
863
844
|
return Qnil;
|
@@ -874,7 +855,7 @@ rbtree_reject(VALUE self)
|
|
874
855
|
}
|
875
856
|
|
876
857
|
static VALUE
|
877
|
-
rbtree_shift_pop(VALUE self, const int
|
858
|
+
rbtree_shift_pop(VALUE self, const int shift)
|
878
859
|
{
|
879
860
|
dict_t* dict = DICT(self);
|
880
861
|
dnode_t* node;
|
@@ -889,10 +870,10 @@ rbtree_shift_pop(VALUE self, const int mode)
|
|
889
870
|
return IFNONE(self);
|
890
871
|
}
|
891
872
|
|
892
|
-
if (
|
893
|
-
node = dict_first(dict);
|
894
|
-
else
|
873
|
+
if (shift)
|
895
874
|
node = dict_last(dict);
|
875
|
+
else
|
876
|
+
node = dict_first(dict);
|
896
877
|
ret = ASSOC(node);
|
897
878
|
dict_delete_free(dict, node);
|
898
879
|
return ret;
|
@@ -1088,7 +1069,12 @@ to_hash_i(dnode_t* node, void* hash)
|
|
1088
1069
|
VALUE
|
1089
1070
|
rbtree_to_hash(VALUE self)
|
1090
1071
|
{
|
1091
|
-
VALUE hash
|
1072
|
+
VALUE hash;
|
1073
|
+
if (CLASS_OF(self) == MultiRBTree) {
|
1074
|
+
rb_raise(rb_eTypeError, "can't convert MultiRBTree to Hash");
|
1075
|
+
}
|
1076
|
+
|
1077
|
+
hash = rb_hash_new();
|
1092
1078
|
rbtree_for_each(self, to_hash_i, (void*)hash);
|
1093
1079
|
RHASH(hash)->ifnone = IFNONE(self);
|
1094
1080
|
if (FL_TEST(self, RBTREE_PROC_DEFAULT))
|
@@ -1307,7 +1293,7 @@ rbtree_bound(int argc, VALUE* argv, VALUE self)
|
|
1307
1293
|
}
|
1308
1294
|
|
1309
1295
|
static VALUE
|
1310
|
-
rbtree_first_last(VALUE self, const int
|
1296
|
+
rbtree_first_last(VALUE self, const int first)
|
1311
1297
|
{
|
1312
1298
|
dict_t* dict = DICT(self);
|
1313
1299
|
dnode_t* node;
|
@@ -1319,7 +1305,7 @@ rbtree_first_last(VALUE self, const int mode)
|
|
1319
1305
|
return IFNONE(self);
|
1320
1306
|
}
|
1321
1307
|
|
1322
|
-
if (
|
1308
|
+
if (first)
|
1323
1309
|
node = dict_first(dict);
|
1324
1310
|
else
|
1325
1311
|
node = dict_last(dict);
|
@@ -1335,7 +1321,7 @@ rbtree_first_last(VALUE self, const int mode)
|
|
1335
1321
|
VALUE
|
1336
1322
|
rbtree_first(VALUE self)
|
1337
1323
|
{
|
1338
|
-
return rbtree_first_last(self,
|
1324
|
+
return rbtree_first_last(self, 1);
|
1339
1325
|
}
|
1340
1326
|
|
1341
1327
|
/*
|
@@ -1347,7 +1333,7 @@ rbtree_first(VALUE self)
|
|
1347
1333
|
VALUE
|
1348
1334
|
rbtree_last(VALUE self)
|
1349
1335
|
{
|
1350
|
-
return rbtree_first_last(self,
|
1336
|
+
return rbtree_first_last(self, 0);
|
1351
1337
|
}
|
1352
1338
|
|
1353
1339
|
/*
|
@@ -1359,11 +1345,11 @@ rbtree_last(VALUE self)
|
|
1359
1345
|
*
|
1360
1346
|
* Sets a proc to compare keys and readjusts elements using the given
|
1361
1347
|
* block or a Proc object given as the argument. The block takes two
|
1362
|
-
* key
|
1363
|
-
* first argument is less than, equal to, or greater than the
|
1364
|
-
* one. If no block is given it just readjusts elements using
|
1365
|
-
* comparison block. If nil is given as the argument it sets
|
1366
|
-
* comparison block.
|
1348
|
+
* arguments of a key and returns negative, 0, or positive depending
|
1349
|
+
* on the first argument is less than, equal to, or greater than the
|
1350
|
+
* second one. If no block is given it just readjusts elements using
|
1351
|
+
* current comparison block. If nil is given as the argument it sets
|
1352
|
+
* default comparison block.
|
1367
1353
|
*/
|
1368
1354
|
VALUE
|
1369
1355
|
rbtree_readjust(int argc, VALUE* argv, VALUE self)
|
@@ -1482,20 +1468,6 @@ rbtree_pretty_print_cycle(VALUE self, VALUE pp)
|
|
1482
1468
|
|
1483
1469
|
/*********************************************************************/
|
1484
1470
|
|
1485
|
-
#ifndef HAVE_RB_MARSHAL_DUMP
|
1486
|
-
static VALUE
|
1487
|
-
rb_marshal_dump(VALUE obj, VALUE port)
|
1488
|
-
{
|
1489
|
-
return rb_funcall(rb_mMarshal, id_dump, 2, obj, port);
|
1490
|
-
}
|
1491
|
-
|
1492
|
-
static VALUE
|
1493
|
-
rb_marshal_load(VALUE port)
|
1494
|
-
{
|
1495
|
-
return rb_funcall(rb_mMarshal, id_load, 1, port);
|
1496
|
-
}
|
1497
|
-
#endif
|
1498
|
-
|
1499
1471
|
static each_return_t
|
1500
1472
|
to_flatten_ary_i(dnode_t* node, void* ary)
|
1501
1473
|
{
|
@@ -1554,10 +1526,10 @@ rbtree_s_load(VALUE klass, VALUE str)
|
|
1554
1526
|
/*********************************************************************/
|
1555
1527
|
|
1556
1528
|
/*
|
1557
|
-
* RBTree is a sorted associative collection
|
1558
|
-
*
|
1559
|
-
*
|
1560
|
-
*
|
1529
|
+
* RBTree is a sorted associative collection that is implemented with
|
1530
|
+
* Red-Black Tree. The elements of RBTree are ordered and its interface
|
1531
|
+
* is the almost same as Hash, so simply you can consider RBTree sorted
|
1532
|
+
* Hash.
|
1561
1533
|
*
|
1562
1534
|
* Red-Black Tree is a kind of binary tree that automatically balances
|
1563
1535
|
* by itself when a node is inserted or deleted. Thus the complexity
|
@@ -1565,25 +1537,45 @@ rbtree_s_load(VALUE klass, VALUE str)
|
|
1565
1537
|
* case. On the other hand the complexity of Hash is O(1). Because
|
1566
1538
|
* Hash is unordered the data structure is more effective than
|
1567
1539
|
* Red-Black Tree as an associative collection.
|
1540
|
+
*
|
1541
|
+
* The elements of RBTree are sorted with natural ordering (by <=>
|
1542
|
+
* method) of its keys or by a comparator(Proc) set by readjust
|
1543
|
+
* method. It means all keys in RBTree should be comparable with each
|
1544
|
+
* other. Or a comparator that takes two arguments of a key should return
|
1545
|
+
* negative, 0, or positive depending on the first argument is less than,
|
1546
|
+
* equal to, or greater than the second one.
|
1547
|
+
*
|
1548
|
+
* The interface of RBTree is the almost same as Hash and there are a
|
1549
|
+
* few methods to take advantage of the ordering:
|
1550
|
+
*
|
1551
|
+
* * lower_bound, upper_bound, bound
|
1552
|
+
* * first, last
|
1553
|
+
* * shift, pop
|
1554
|
+
* * reverse_each
|
1555
|
+
*
|
1556
|
+
* Note: while iterating RBTree (e.g. in a block of each method), it is
|
1557
|
+
* not modifiable, or TypeError is thrown.
|
1558
|
+
*
|
1559
|
+
* RBTree supoorts pretty printing using pp.
|
1560
|
+
*
|
1561
|
+
* This library contains two classes. One is RBTree and the other is
|
1562
|
+
* MultiRBTree that is a parent class of RBTree. RBTree does not allow
|
1563
|
+
* duplications of keys but MultiRBTree does.
|
1568
1564
|
*
|
1569
|
-
*
|
1570
|
-
*
|
1571
|
-
*
|
1572
|
-
*
|
1573
|
-
*
|
1574
|
-
*
|
1575
|
-
*
|
1576
|
-
*
|
1577
|
-
*
|
1578
|
-
*
|
1579
|
-
*
|
1580
|
-
*
|
1581
|
-
*
|
1582
|
-
*
|
1583
|
-
* Pretty printing is available for RBTree by using pp.rb. The output
|
1584
|
-
* of pp is easier than p to read. Just call Kernel#pp for the object.
|
1585
|
-
*
|
1586
|
-
* MultiRBTree that allows duplicates of keys is also available.
|
1565
|
+
* require "rbtree"
|
1566
|
+
*
|
1567
|
+
* rbtree = RBTree["c", 10, "a", 20]
|
1568
|
+
* rbtree["b"] = 30
|
1569
|
+
* p rbtree["b"] # => 30
|
1570
|
+
* rbtree.each do |k, v|
|
1571
|
+
* p [k, v]
|
1572
|
+
* end # => ["a", 20] ["b", 30] ["c", 10]
|
1573
|
+
*
|
1574
|
+
* mrbtree = MultiRBTree["c", 10, "a", 20, "e", 30, "a", 40]
|
1575
|
+
* p mrbtree.lower_bound("b") # => ["c", 10]
|
1576
|
+
* mrbtree.bound("a", "d") do |k, v|
|
1577
|
+
* p [k, v]
|
1578
|
+
* end # => ["a", 20] ["a", 40] ["c", 10]
|
1587
1579
|
*/
|
1588
1580
|
void Init_rbtree()
|
1589
1581
|
{
|
@@ -1591,21 +1583,13 @@ void Init_rbtree()
|
|
1591
1583
|
RBTree = rb_define_class("RBTree", MultiRBTree);
|
1592
1584
|
|
1593
1585
|
rb_include_module(MultiRBTree, rb_mEnumerable);
|
1594
|
-
|
1595
|
-
#ifdef HAVE_OBJECT_ALLOCATE
|
1586
|
+
|
1596
1587
|
rb_define_alloc_func(MultiRBTree, rbtree_alloc);
|
1597
|
-
|
1598
|
-
rb_define_singleton_method(MultiRBTree, "new", rbtree_s_new, -1);
|
1599
|
-
#endif
|
1588
|
+
|
1600
1589
|
rb_define_singleton_method(MultiRBTree, "[]", rbtree_s_create, -1);
|
1601
1590
|
|
1602
1591
|
rb_define_method(MultiRBTree, "initialize", rbtree_initialize, -1);
|
1603
|
-
|
1604
|
-
#ifdef HAVE_RB_OBJ_INIT_COPY
|
1605
1592
|
rb_define_method(MultiRBTree, "initialize_copy", rbtree_initialize_copy, 1);
|
1606
|
-
#else
|
1607
|
-
rb_define_method(MultiRBTree, "clone", rbtree_clone, 0);
|
1608
|
-
#endif
|
1609
1593
|
|
1610
1594
|
rb_define_method(MultiRBTree, "to_a", rbtree_to_a, 0);
|
1611
1595
|
rb_define_method(MultiRBTree, "to_s", rbtree_to_s, 0);
|
@@ -1667,11 +1651,6 @@ void Init_rbtree()
|
|
1667
1651
|
|
1668
1652
|
rb_define_method(MultiRBTree, "_dump", rbtree_dump, 1);
|
1669
1653
|
rb_define_singleton_method(MultiRBTree, "_load", rbtree_s_load, 1);
|
1670
|
-
#ifndef HAVE_RB_MARSHAL_DUMP
|
1671
|
-
rb_mMarshal = rb_path2class("Marshal");
|
1672
|
-
id_dump = rb_intern("dump");
|
1673
|
-
id_load = rb_intern("load");
|
1674
|
-
#endif
|
1675
1654
|
|
1676
1655
|
id_bound = rb_intern("bound");
|
1677
1656
|
id_cmp = rb_intern("<=>");
|