algorithms 0.2.0 → 0.3.0
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 +4 -0
- data/Manifest +8 -6
- data/README.markdown +1 -0
- data/Rakefile +1 -1
- data/algorithms.gemspec +4 -4
- data/benchmarks/treemaps.rb +25 -10
- data/ext/containers/rbtree_map/rbtree.c +37 -12
- data/ext/containers/splaytree_map/splaytree.c +151 -102
- data/lib/algorithms.rb +1 -0
- data/lib/containers/kd_tree.rb +40 -17
- data/spec/kd_expected_out.txt +10000 -0
- data/spec/kd_test_in.txt +10000 -0
- data/spec/kd_tree_spec.rb +31 -1
- data/spec/map_gc_mark_spec.rb +27 -0
- data/spec/splay_tree_map_spec.rb +4 -0
- metadata +12 -10
- data/spec/rb_tree_map_gc_mark_spec.rb +0 -25
data/History.txt
CHANGED
data/Manifest
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest
|
3
|
+
README.markdown
|
4
|
+
Rakefile
|
1
5
|
algorithms.gemspec
|
2
6
|
benchmarks/deque.rb
|
3
7
|
benchmarks/sorts.rb
|
@@ -8,10 +12,9 @@ ext/containers/rbtree_map/extconf.rb
|
|
8
12
|
ext/containers/rbtree_map/rbtree.c
|
9
13
|
ext/containers/splaytree_map/extconf.rb
|
10
14
|
ext/containers/splaytree_map/splaytree.c
|
11
|
-
|
15
|
+
lib/algorithms.rb
|
12
16
|
lib/algorithms/search.rb
|
13
17
|
lib/algorithms/sort.rb
|
14
|
-
lib/algorithms.rb
|
15
18
|
lib/containers/deque.rb
|
16
19
|
lib/containers/heap.rb
|
17
20
|
lib/containers/kd_tree.rb
|
@@ -22,16 +25,15 @@ lib/containers/splay_tree_map.rb
|
|
22
25
|
lib/containers/stack.rb
|
23
26
|
lib/containers/suffix_array.rb
|
24
27
|
lib/containers/trie.rb
|
25
|
-
Manifest
|
26
|
-
Rakefile
|
27
|
-
README.markdown
|
28
28
|
spec/deque_gc_mark_spec.rb
|
29
29
|
spec/deque_spec.rb
|
30
30
|
spec/heap_spec.rb
|
31
|
+
spec/kd_expected_out.txt
|
32
|
+
spec/kd_test_in.txt
|
31
33
|
spec/kd_tree_spec.rb
|
34
|
+
spec/map_gc_mark_spec.rb
|
32
35
|
spec/priority_queue_spec.rb
|
33
36
|
spec/queue_spec.rb
|
34
|
-
spec/rb_tree_map_gc_mark_spec.rb
|
35
37
|
spec/rb_tree_map_spec.rb
|
36
38
|
spec/search_spec.rb
|
37
39
|
spec/sort_spec.rb
|
data/README.markdown
CHANGED
@@ -31,6 +31,7 @@ Done so far:
|
|
31
31
|
* Splay Trees Containers::SplayTreeMap, Containers::CSplayTreeMap (C extension), Containers::RubySplayTreeMap
|
32
32
|
* Tries Containers::Trie
|
33
33
|
* Suffix Array Containers::SuffixArray
|
34
|
+
* kd Tree Containers::KDTree
|
34
35
|
|
35
36
|
* Search algorithms
|
36
37
|
- Binary Search Algorithms::Search.binary_search
|
data/Rakefile
CHANGED
data/algorithms.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{algorithms}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.3.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Kanwei Li"]
|
9
|
-
s.date = %q{2009-
|
9
|
+
s.date = %q{2009-11-16}
|
10
10
|
s.description = %q{A library of algorithms and containers.}
|
11
11
|
s.email = %q{kanwei@gmail.com}
|
12
12
|
s.extensions = ["ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/splaytree_map/extconf.rb"]
|
13
|
-
s.extra_rdoc_files = ["ext/containers/deque/deque.c", "ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/rbtree_map/rbtree.c", "ext/containers/splaytree_map/extconf.rb", "ext/containers/splaytree_map/splaytree.c", "lib/algorithms
|
14
|
-
s.files = ["algorithms.gemspec", "benchmarks/deque.rb", "benchmarks/sorts.rb", "benchmarks/treemaps.rb", "ext/containers/deque/deque.c", "ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/rbtree_map/rbtree.c", "ext/containers/splaytree_map/extconf.rb", "ext/containers/splaytree_map/splaytree.c", "
|
13
|
+
s.extra_rdoc_files = ["README.markdown", "ext/containers/deque/deque.c", "ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/rbtree_map/rbtree.c", "ext/containers/splaytree_map/extconf.rb", "ext/containers/splaytree_map/splaytree.c", "lib/algorithms.rb", "lib/algorithms/search.rb", "lib/algorithms/sort.rb", "lib/containers/deque.rb", "lib/containers/heap.rb", "lib/containers/kd_tree.rb", "lib/containers/priority_queue.rb", "lib/containers/queue.rb", "lib/containers/rb_tree_map.rb", "lib/containers/splay_tree_map.rb", "lib/containers/stack.rb", "lib/containers/suffix_array.rb", "lib/containers/trie.rb"]
|
14
|
+
s.files = ["History.txt", "Manifest", "README.markdown", "Rakefile", "algorithms.gemspec", "benchmarks/deque.rb", "benchmarks/sorts.rb", "benchmarks/treemaps.rb", "ext/containers/deque/deque.c", "ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/rbtree_map/rbtree.c", "ext/containers/splaytree_map/extconf.rb", "ext/containers/splaytree_map/splaytree.c", "lib/algorithms.rb", "lib/algorithms/search.rb", "lib/algorithms/sort.rb", "lib/containers/deque.rb", "lib/containers/heap.rb", "lib/containers/kd_tree.rb", "lib/containers/priority_queue.rb", "lib/containers/queue.rb", "lib/containers/rb_tree_map.rb", "lib/containers/splay_tree_map.rb", "lib/containers/stack.rb", "lib/containers/suffix_array.rb", "lib/containers/trie.rb", "spec/deque_gc_mark_spec.rb", "spec/deque_spec.rb", "spec/heap_spec.rb", "spec/kd_expected_out.txt", "spec/kd_test_in.txt", "spec/kd_tree_spec.rb", "spec/map_gc_mark_spec.rb", "spec/priority_queue_spec.rb", "spec/queue_spec.rb", "spec/rb_tree_map_spec.rb", "spec/search_spec.rb", "spec/sort_spec.rb", "spec/splay_tree_map_spec.rb", "spec/stack_spec.rb", "spec/suffix_array_spec.rb", "spec/trie_spec.rb"]
|
15
15
|
s.has_rdoc = true
|
16
16
|
s.homepage = %q{http://rubyforge.org/projects/algorithms/}
|
17
17
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Algorithms", "--main", "README.markdown"]
|
data/benchmarks/treemaps.rb
CHANGED
@@ -1,20 +1,19 @@
|
|
1
1
|
$: << File.join(File.expand_path(File.dirname(__FILE__)), '../lib')
|
2
2
|
require 'algorithms'
|
3
|
-
include
|
3
|
+
include Containers
|
4
4
|
|
5
5
|
require 'rubygems'
|
6
6
|
require 'rbench'
|
7
7
|
|
8
|
-
RBench.run(
|
8
|
+
RBench.run(2) do
|
9
9
|
trees = %w(hash rbtree splaytree)
|
10
10
|
trees.each { |tree| self.send(:column, tree.intern) }
|
11
11
|
|
12
|
-
rbtree =
|
13
|
-
splaytree =
|
12
|
+
rbtree = RBTreeMap.new
|
13
|
+
splaytree = SplayTreeMap.new
|
14
14
|
hash = Hash.new
|
15
15
|
|
16
|
-
random_array = Array.new(
|
17
|
-
num = 1000
|
16
|
+
random_array = Array.new(300000) { |i| rand(i) }
|
18
17
|
|
19
18
|
report "Insertion" do
|
20
19
|
rbtree { random_array.each_with_index { |x,index| rbtree[index] = x } }
|
@@ -22,15 +21,31 @@ RBench.run(10) do
|
|
22
21
|
hash { random_array.each_with_index { |x,index| hash[index] = x } }
|
23
22
|
end
|
24
23
|
|
25
|
-
report "has_key?" do
|
26
|
-
rbtree {
|
27
|
-
splaytree {
|
28
|
-
hash {
|
24
|
+
report "has_key? (linear order)" do
|
25
|
+
rbtree { random_array.each { |n| rbtree.has_key?(n) } }
|
26
|
+
splaytree { random_array.each { |n| splaytree.has_key?(n) } }
|
27
|
+
hash { random_array.each { |n| hash.has_key?(n) } }
|
29
28
|
end
|
30
29
|
|
31
30
|
report "Lookup in sorted order" do
|
32
31
|
rbtree { rbtree.each { |k, v| k } }
|
33
32
|
splaytree { splaytree.each { |k, v| k } }
|
34
33
|
hash { hash.sort.each { |k, v| k } }
|
34
|
+
|
35
|
+
# a1, a2, a3 = [], [], []
|
36
|
+
# rbtree.each { |k, v| a1 << k }
|
37
|
+
# splaytree.each { |k, v| a2 << k }
|
38
|
+
# hash.sort.each { |k, v| a3 << k }
|
39
|
+
#
|
40
|
+
# puts "Lookup correct" if a1 == a2 && a1 == a3
|
35
41
|
end
|
42
|
+
|
43
|
+
report "Random lookups in a smaller subset" do
|
44
|
+
select_subset = random_array[0..random_array.size/20] # 5%
|
45
|
+
size = select_subset.size
|
46
|
+
rbtree { 10000.times { rbtree[ select_subset[rand(size)] ] } }
|
47
|
+
splaytree { 10000.times { splaytree[ select_subset[rand(size)] ] } }
|
48
|
+
hash { 10000.times { hash[ select_subset[rand(size)] ] } }
|
49
|
+
end
|
50
|
+
|
36
51
|
end
|
@@ -22,6 +22,11 @@ typedef struct {
|
|
22
22
|
rbtree_node *root;
|
23
23
|
} rbtree;
|
24
24
|
|
25
|
+
typedef struct struct_ll_node {
|
26
|
+
rbtree_node *node;
|
27
|
+
struct struct_ll_node *next;
|
28
|
+
} ll_node;
|
29
|
+
|
25
30
|
static void recursively_free_nodes(rbtree_node *node) {
|
26
31
|
if(node) {
|
27
32
|
recursively_free_nodes(node->left);
|
@@ -292,8 +297,8 @@ static int rbtree_compare_function(VALUE a, VALUE b) {
|
|
292
297
|
if (x > y) return 1;
|
293
298
|
return -1;
|
294
299
|
}
|
295
|
-
if (TYPE(a) == T_STRING &&
|
296
|
-
|
300
|
+
if (TYPE(a) == T_STRING && rb_obj_is_kind_of(a, rb_cString) &&
|
301
|
+
TYPE(b) == T_STRING && rb_obj_is_kind_of(b, rb_cString)) {
|
297
302
|
return rb_str_cmp(a, b);
|
298
303
|
}
|
299
304
|
return FIX2INT(rb_funcall((VALUE) a, id_compare_operator, 1, (VALUE) b));
|
@@ -304,19 +309,39 @@ static VALUE rbtree_init(VALUE self)
|
|
304
309
|
return self;
|
305
310
|
}
|
306
311
|
|
307
|
-
static void recursively_mark_nodes(rbtree_node *node) {
|
308
|
-
if(node) {
|
309
|
-
rb_gc_mark(node->key);
|
310
|
-
rb_gc_mark(node->value);
|
311
|
-
recursively_mark_nodes(node->left);
|
312
|
-
recursively_mark_nodes(node->right);
|
313
|
-
}
|
314
|
-
}
|
315
|
-
|
316
312
|
static void rbtree_mark(void *ptr) {
|
313
|
+
ll_node *current, *new, *last, *old;
|
317
314
|
if (ptr) {
|
318
315
|
rbtree *tree = ptr;
|
319
|
-
|
316
|
+
|
317
|
+
if (tree->root) {
|
318
|
+
current = ALLOC(ll_node);
|
319
|
+
last = current;
|
320
|
+
current->node = tree->root;
|
321
|
+
current->next = NULL;
|
322
|
+
|
323
|
+
while(current) {
|
324
|
+
rb_gc_mark(current->node->key);
|
325
|
+
rb_gc_mark(current->node->value);
|
326
|
+
if (current->node->left) {
|
327
|
+
new = ALLOC(ll_node);
|
328
|
+
new->node = current->node->left;
|
329
|
+
new->next = NULL;
|
330
|
+
last->next = new;
|
331
|
+
last = new;
|
332
|
+
}
|
333
|
+
if (current->node->right) {
|
334
|
+
new = ALLOC(ll_node);
|
335
|
+
new->node = current->node->right;
|
336
|
+
new->next = NULL;
|
337
|
+
last->next = new;
|
338
|
+
last = new;
|
339
|
+
}
|
340
|
+
old = current;
|
341
|
+
current = current->next;
|
342
|
+
free(old);
|
343
|
+
}
|
344
|
+
}
|
320
345
|
}
|
321
346
|
}
|
322
347
|
|
@@ -1,19 +1,29 @@
|
|
1
1
|
#include "ruby.h"
|
2
2
|
|
3
|
+
#define node_size(x) (((x)==NULL) ? 0 : ((x)->size))
|
4
|
+
|
5
|
+
/* Using http://www.link.cs.cmu.edu/link/ftp-site/splaying/top-down-size-splay.c as reference,
|
6
|
+
written by D. Sleator <sleator@cs.cmu.edu>, January 1994.
|
7
|
+
*/
|
8
|
+
|
3
9
|
typedef struct struct_splaytree_node {
|
4
10
|
VALUE key;
|
5
11
|
VALUE value;
|
12
|
+
int size;
|
6
13
|
struct struct_splaytree_node *left;
|
7
14
|
struct struct_splaytree_node *right;
|
8
15
|
} splaytree_node;
|
9
16
|
|
10
17
|
typedef struct {
|
11
18
|
int (*compare_function)(VALUE key1, VALUE key2);
|
12
|
-
int size;
|
13
19
|
splaytree_node *root;
|
14
|
-
splaytree_node *header;
|
15
20
|
} splaytree;
|
16
21
|
|
22
|
+
typedef struct struct_ll_node {
|
23
|
+
splaytree_node *node;
|
24
|
+
struct struct_ll_node *next;
|
25
|
+
} ll_node;
|
26
|
+
|
17
27
|
static void recursively_free_nodes(splaytree_node *node) {
|
18
28
|
if(node) {
|
19
29
|
recursively_free_nodes(node->left);
|
@@ -29,55 +39,75 @@ static splaytree* get_tree_from_self(VALUE self) {
|
|
29
39
|
return tree;
|
30
40
|
}
|
31
41
|
|
32
|
-
static
|
33
|
-
int cmp, cmp2;
|
34
|
-
splaytree_node
|
42
|
+
static splaytree_node* splay(splaytree *tree, splaytree_node *n, VALUE key) {
|
43
|
+
int cmp, cmp2, root_size, l_size, r_size;
|
44
|
+
splaytree_node N;
|
45
|
+
splaytree_node *l, *r, *y;
|
35
46
|
|
36
|
-
|
37
|
-
r = tree->header;
|
38
|
-
t = tree->root;
|
47
|
+
if (!n) return n;
|
39
48
|
|
40
|
-
|
41
|
-
|
49
|
+
N.left = N.right = NULL;
|
50
|
+
l = r = &N;
|
51
|
+
root_size = node_size(n);
|
52
|
+
l_size = r_size = 0;
|
42
53
|
|
43
54
|
while(1) {
|
44
|
-
cmp = tree->compare_function(key,
|
55
|
+
cmp = tree->compare_function(key, n->key);
|
45
56
|
if (cmp == -1) {
|
46
|
-
if (!
|
47
|
-
cmp2 = tree->compare_function(key,
|
57
|
+
if (!n->left) break;
|
58
|
+
cmp2 = tree->compare_function(key, n->left->key);
|
48
59
|
if (cmp2 == -1) {
|
49
|
-
y =
|
50
|
-
|
51
|
-
y->right =
|
52
|
-
|
53
|
-
|
60
|
+
y = n->left;
|
61
|
+
n->left = y->right;
|
62
|
+
y->right = n;
|
63
|
+
n->size = node_size(n->left) + node_size(n->right) + 1;
|
64
|
+
n = y;
|
65
|
+
if (!n->left) break;
|
54
66
|
}
|
55
|
-
r->left =
|
56
|
-
r =
|
57
|
-
|
58
|
-
|
59
|
-
else if (cmp == 1) {
|
60
|
-
if (!
|
61
|
-
cmp2 = tree->compare_function(key,
|
67
|
+
r->left = n;
|
68
|
+
r = n;
|
69
|
+
n = n->left;
|
70
|
+
r_size += 1 + node_size(r->right);
|
71
|
+
} else if (cmp == 1) {
|
72
|
+
if (!n->right) break;
|
73
|
+
cmp2 = tree->compare_function(key, n->right->key);
|
62
74
|
if (cmp2 == 1) {
|
63
|
-
y =
|
64
|
-
|
65
|
-
y->left =
|
66
|
-
|
67
|
-
|
75
|
+
y = n->right;
|
76
|
+
n->right = y->left;
|
77
|
+
y->left = n;
|
78
|
+
n->size = node_size(n->left) + node_size(n->right) + 1;
|
79
|
+
n = y;
|
80
|
+
if (!n->right) break;
|
68
81
|
}
|
69
|
-
l->right =
|
70
|
-
l =
|
71
|
-
|
82
|
+
l->right = n;
|
83
|
+
l = n;
|
84
|
+
n = n->right;
|
85
|
+
l_size += 1 + node_size(l->left);
|
72
86
|
} else {
|
73
87
|
break;
|
74
88
|
}
|
75
89
|
}
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
90
|
+
|
91
|
+
l_size += node_size(n->left);
|
92
|
+
r_size += node_size(n->right);
|
93
|
+
n->size = l_size + r_size + 1;
|
94
|
+
l->right = r->left = NULL;
|
95
|
+
|
96
|
+
for (y = N.right; y != NULL; y = y->right) {
|
97
|
+
y->size = l_size;
|
98
|
+
l_size -= 1 + node_size(y->left);
|
99
|
+
}
|
100
|
+
for (y = N.left; y != NULL; y = y->left) {
|
101
|
+
y->size = r_size;
|
102
|
+
r_size -= 1 + node_size(y->right);
|
103
|
+
}
|
104
|
+
|
105
|
+
l->right = n->left;
|
106
|
+
r->left = n->right;
|
107
|
+
n->left = N.right;
|
108
|
+
n->right = N.left;
|
109
|
+
|
110
|
+
return n;
|
81
111
|
}
|
82
112
|
|
83
113
|
static int height(splaytree_node *h) {
|
@@ -95,8 +125,6 @@ static splaytree* create_splaytree(int (*compare_function)(VALUE, VALUE)) {
|
|
95
125
|
splaytree *tree = ALLOC(splaytree);
|
96
126
|
tree->compare_function = compare_function;
|
97
127
|
tree->root = NULL;
|
98
|
-
tree->size = 0;
|
99
|
-
tree->header = ALLOC(splaytree_node);
|
100
128
|
return tree;
|
101
129
|
}
|
102
130
|
|
@@ -109,44 +137,46 @@ static splaytree_node* create_node(VALUE key, VALUE value) {
|
|
109
137
|
return new_node;
|
110
138
|
}
|
111
139
|
|
112
|
-
static
|
140
|
+
static splaytree_node* insert(splaytree *tree, splaytree_node *n, VALUE key, VALUE value) {
|
113
141
|
int cmp;
|
114
142
|
splaytree_node *new_node;
|
115
143
|
|
116
|
-
if (
|
117
|
-
|
118
|
-
tree->
|
119
|
-
|
120
|
-
|
144
|
+
if (n) {
|
145
|
+
n = splay(tree, n, key);
|
146
|
+
cmp = tree->compare_function(key, n->key);
|
147
|
+
if (cmp == 0) {
|
148
|
+
n->value = value;
|
149
|
+
return n;
|
150
|
+
}
|
121
151
|
}
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
if (cmp == 0) {
|
126
|
-
tree->root->value = value;
|
127
|
-
return;
|
152
|
+
new_node = create_node(key, value);
|
153
|
+
if (!n) {
|
154
|
+
new_node->left = new_node->right = NULL;
|
128
155
|
} else {
|
129
|
-
|
130
|
-
if (cmp
|
131
|
-
new_node->left =
|
132
|
-
new_node->right =
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
new_node->
|
137
|
-
|
156
|
+
cmp = tree->compare_function(key, n->key);
|
157
|
+
if (cmp < 0) {
|
158
|
+
new_node->left = n->left;
|
159
|
+
new_node->right = n;
|
160
|
+
n->left = NULL;
|
161
|
+
n->size = 1 + node_size(n->right);
|
162
|
+
} else {
|
163
|
+
new_node->right = n->right;
|
164
|
+
new_node->left = n;
|
165
|
+
n->right = NULL;
|
166
|
+
n->size = 1 + node_size(n->left);
|
138
167
|
}
|
139
|
-
tree->root = new_node;
|
140
|
-
tree->size += 1;
|
141
168
|
}
|
169
|
+
new_node->size = 1 + node_size(new_node->left) + node_size(new_node->right);
|
170
|
+
return new_node;
|
142
171
|
}
|
143
172
|
|
144
173
|
static VALUE get(splaytree *tree, VALUE key) {
|
145
174
|
int cmp;
|
175
|
+
|
146
176
|
if (!tree->root)
|
147
177
|
return Qnil;
|
148
|
-
|
149
|
-
splay(tree, key);
|
178
|
+
|
179
|
+
tree->root = splay(tree, tree->root, key);
|
150
180
|
cmp = tree->compare_function(key, tree->root->key);
|
151
181
|
if (cmp == 0) {
|
152
182
|
return tree->root->value;
|
@@ -154,29 +184,28 @@ static VALUE get(splaytree *tree, VALUE key) {
|
|
154
184
|
return Qnil;
|
155
185
|
}
|
156
186
|
|
157
|
-
static
|
158
|
-
int cmp;
|
159
|
-
splaytree_node *x
|
160
|
-
|
161
|
-
|
162
|
-
splay(tree, key);
|
163
|
-
cmp = tree->compare_function(key,
|
187
|
+
static splaytree_node* delete(splaytree *tree, splaytree_node *n, VALUE key, VALUE *deleted) {
|
188
|
+
int cmp, tsize;
|
189
|
+
splaytree_node *x;
|
190
|
+
|
191
|
+
tsize = n->size;
|
192
|
+
n = splay(tree, n, key);
|
193
|
+
cmp = tree->compare_function(key, n->key);
|
164
194
|
if (cmp == 0) {
|
165
|
-
deleted =
|
166
|
-
|
167
|
-
|
168
|
-
tree->root = tree->root->right;
|
195
|
+
*deleted = n->value;
|
196
|
+
if (!n->left) {
|
197
|
+
x = n->right;
|
169
198
|
} else {
|
170
|
-
x = tree->
|
171
|
-
|
172
|
-
splay(tree, key);
|
173
|
-
tree->root->right = x;
|
199
|
+
x = splay(tree, n->left, key);
|
200
|
+
x->right = n->right;
|
174
201
|
}
|
175
|
-
free(
|
176
|
-
|
177
|
-
|
202
|
+
free(n);
|
203
|
+
if (x) {
|
204
|
+
x->size = tsize-1;
|
205
|
+
}
|
206
|
+
return x;
|
178
207
|
}
|
179
|
-
return
|
208
|
+
return n;
|
180
209
|
}
|
181
210
|
|
182
211
|
static splaytree* splaytree_each_node(splaytree *tree, splaytree_node *node, void (*each)(splaytree *tree_, splaytree_node *node_, void* args), void* arguments) {
|
@@ -211,8 +240,8 @@ static int splaytree_compare_function(VALUE a, VALUE b) {
|
|
211
240
|
if (x > y) return 1;
|
212
241
|
return -1;
|
213
242
|
}
|
214
|
-
if (TYPE(a) == T_STRING &&
|
215
|
-
|
243
|
+
if (TYPE(a) == T_STRING && rb_obj_is_kind_of(a, rb_cString) &&
|
244
|
+
TYPE(b) == T_STRING && rb_obj_is_kind_of(b, rb_cString)) {
|
216
245
|
return rb_str_cmp(a, b);
|
217
246
|
}
|
218
247
|
return FIX2INT(rb_funcall((VALUE) a, id_compare_operator, 1, (VALUE) b));
|
@@ -223,19 +252,39 @@ static VALUE splaytree_init(VALUE self)
|
|
223
252
|
return self;
|
224
253
|
}
|
225
254
|
|
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
255
|
static void splaytree_mark(void *ptr) {
|
256
|
+
ll_node *current, *new, *last, *old;
|
236
257
|
if (ptr) {
|
237
258
|
splaytree *tree = ptr;
|
238
|
-
|
259
|
+
|
260
|
+
if (tree->root) {
|
261
|
+
current = ALLOC(ll_node);
|
262
|
+
last = current;
|
263
|
+
current->node = tree->root;
|
264
|
+
current->next = NULL;
|
265
|
+
|
266
|
+
while(current) {
|
267
|
+
rb_gc_mark(current->node->key);
|
268
|
+
rb_gc_mark(current->node->value);
|
269
|
+
if (current->node->left) {
|
270
|
+
new = ALLOC(ll_node);
|
271
|
+
new->node = current->node->left;
|
272
|
+
new->next = NULL;
|
273
|
+
last->next = new;
|
274
|
+
last = new;
|
275
|
+
}
|
276
|
+
if (current->node->right) {
|
277
|
+
new = ALLOC(ll_node);
|
278
|
+
new->node = current->node->right;
|
279
|
+
new->next = NULL;
|
280
|
+
last->next = new;
|
281
|
+
last = new;
|
282
|
+
}
|
283
|
+
old = current;
|
284
|
+
current = current->next;
|
285
|
+
free(old);
|
286
|
+
}
|
287
|
+
}
|
239
288
|
}
|
240
289
|
}
|
241
290
|
|
@@ -243,7 +292,6 @@ static void splaytree_free(void *ptr) {
|
|
243
292
|
if (ptr) {
|
244
293
|
splaytree *tree = ptr;
|
245
294
|
recursively_free_nodes(tree->root);
|
246
|
-
free(tree->header);
|
247
295
|
free(tree);
|
248
296
|
}
|
249
297
|
}
|
@@ -255,7 +303,7 @@ static VALUE splaytree_alloc(VALUE klass) {
|
|
255
303
|
|
256
304
|
static VALUE splaytree_push(VALUE self, VALUE key, VALUE value) {
|
257
305
|
splaytree *tree = get_tree_from_self(self);
|
258
|
-
insert(tree, key, value);
|
306
|
+
tree->root = insert(tree, tree->root, key, value);
|
259
307
|
return value;
|
260
308
|
}
|
261
309
|
|
@@ -266,7 +314,8 @@ static VALUE splaytree_get(VALUE self, VALUE key) {
|
|
266
314
|
|
267
315
|
static VALUE splaytree_size(VALUE self) {
|
268
316
|
splaytree *tree = get_tree_from_self(self);
|
269
|
-
return INT2NUM(
|
317
|
+
if(!tree->root) { return INT2NUM(0); }
|
318
|
+
return INT2NUM(tree->root->size);
|
270
319
|
}
|
271
320
|
|
272
321
|
static VALUE splaytree_is_empty(VALUE self) {
|
@@ -317,19 +366,19 @@ static VALUE splaytree_max_key(VALUE self) {
|
|
317
366
|
}
|
318
367
|
|
319
368
|
static VALUE splaytree_delete(VALUE self, VALUE key) {
|
369
|
+
VALUE deleted = Qnil;
|
320
370
|
splaytree *tree = get_tree_from_self(self);
|
321
371
|
if(!tree->root)
|
322
372
|
return Qnil;
|
323
373
|
|
324
|
-
|
374
|
+
tree->root = delete(tree, tree->root, key, &deleted);
|
375
|
+
return deleted;
|
325
376
|
}
|
326
377
|
|
327
378
|
static VALUE splaytree_clear(VALUE self) {
|
328
379
|
splaytree *tree = get_tree_from_self(self);
|
329
380
|
recursively_free_nodes(tree->root);
|
330
381
|
tree->root = NULL;
|
331
|
-
tree->size = 0;
|
332
|
-
|
333
382
|
return Qnil;
|
334
383
|
}
|
335
384
|
|