algorithms 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,7 @@
1
+ === April 3, 2009
2
+
3
+ * Finished C refactorization of SplayTree
4
+
1
5
  === March 28, 2009
2
6
 
3
7
  * Implemented SplayTree in C
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
- History.txt
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
@@ -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
@@ -6,7 +6,7 @@ Echoe.new('algorithms') do |p|
6
6
  p.email = 'kanwei@gmail.com'
7
7
  p.summary = 'A library of algorithms and containers.'
8
8
  p.url = 'http://rubyforge.org/projects/algorithms/'
9
- p.version = "0.2.0"
9
+ p.version = "0.3.0"
10
10
  p.runtime_dependencies = []
11
11
  end
12
12
 
@@ -2,16 +2,16 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{algorithms}
5
- s.version = "0.2.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-03-29}
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/search.rb", "lib/algorithms/sort.rb", "lib/algorithms.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", "README.markdown"]
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", "History.txt", "lib/algorithms/search.rb", "lib/algorithms/sort.rb", "lib/algorithms.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", "Manifest", "Rakefile", "README.markdown", "spec/deque_gc_mark_spec.rb", "spec/deque_spec.rb", "spec/heap_spec.rb", "spec/kd_tree_spec.rb", "spec/priority_queue_spec.rb", "spec/queue_spec.rb", "spec/rb_tree_map_gc_mark_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"]
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"]
@@ -1,20 +1,19 @@
1
1
  $: << File.join(File.expand_path(File.dirname(__FILE__)), '../lib')
2
2
  require 'algorithms'
3
- include Algorithms
3
+ include Containers
4
4
 
5
5
  require 'rubygems'
6
6
  require 'rbench'
7
7
 
8
- RBench.run(10) do
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 = Containers::RBTreeMap.new
13
- splaytree = Containers::SplayTreeMap.new
12
+ rbtree = RBTreeMap.new
13
+ splaytree = SplayTreeMap.new
14
14
  hash = Hash.new
15
15
 
16
- random_array = Array.new(10000) { |i| rand(i) }
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 { num.times { |n| rbtree.has_key?(n) } }
27
- splaytree { num.times { |n| splaytree.has_key?(n) } }
28
- hash { num.times { |n| hash.has_key?(n) } }
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 && RBASIC(a)->klass == rb_cString &&
296
- TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) {
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
- recursively_mark_nodes(tree->root);
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 void splay(splaytree *tree, VALUE key) {
33
- int cmp, cmp2;
34
- splaytree_node *l, *r, *t, *y;
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
- l = tree->header;
37
- r = tree->header;
38
- t = tree->root;
47
+ if (!n) return n;
39
48
 
40
- tree->header->left = NULL;
41
- tree->header->right = NULL;
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, t->key);
55
+ cmp = tree->compare_function(key, n->key);
45
56
  if (cmp == -1) {
46
- if (!(t->left)) break;
47
- cmp2 = tree->compare_function(key, t->left->key);
57
+ if (!n->left) break;
58
+ cmp2 = tree->compare_function(key, n->left->key);
48
59
  if (cmp2 == -1) {
49
- y = t->left;
50
- t->left = y->right;
51
- y->right = t;
52
- t = y;
53
- if (!(t->left)) break;
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 = t;
56
- r = t;
57
- t = t->left;
58
- }
59
- else if (cmp == 1) {
60
- if (!(t->right)) break;
61
- cmp2 = tree->compare_function(key, t->right->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 = t->right;
64
- t->right = y->left;
65
- y->left = t;
66
- t = y;
67
- if (!(t->right)) break;
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 = t;
70
- l = t;
71
- t = t->right;
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
- l->right = t->left;
77
- r->left = t->right;
78
- t->left = tree->header->right;
79
- t->right = tree->header->left;
80
- tree->root = t;
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 void insert(splaytree *tree, VALUE key, VALUE value) {
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 (!(tree->root)) {
117
- new_node = create_node(key, value);
118
- tree->root = new_node;
119
- tree->size += 1;
120
- return;
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
- splay(tree, key);
124
- cmp = tree->compare_function(key, tree->root->key);
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
- new_node = create_node(key, value);
130
- if (cmp == -1) {
131
- new_node->left = tree->root->left;
132
- new_node->right = tree->root;
133
- tree->root->left = NULL;
134
- } else { /* cmp == 1 */
135
- new_node->right = tree->root->right;
136
- new_node->left = tree->root;
137
- tree->root->right = NULL;
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 VALUE delete(splaytree *tree, VALUE key) {
158
- int cmp;
159
- splaytree_node *x, *deleted_root;
160
- VALUE deleted;
161
-
162
- splay(tree, key);
163
- cmp = tree->compare_function(key, tree->root->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 = tree->root->value;
166
- deleted_root = tree->root;
167
- if (!(tree->root->left)) {
168
- tree->root = tree->root->right;
195
+ *deleted = n->value;
196
+ if (!n->left) {
197
+ x = n->right;
169
198
  } else {
170
- x = tree->root->right;
171
- tree->root = tree->root->left;
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(deleted_root);
176
- tree->size -= 1;
177
- return deleted;
202
+ free(n);
203
+ if (x) {
204
+ x->size = tsize-1;
205
+ }
206
+ return x;
178
207
  }
179
- return Qnil;
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 && RBASIC(a)->klass == rb_cString &&
215
- TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) {
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
- recursively_mark_nodes(tree->root);
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(tree->size);
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
- return delete(tree, key);
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