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.
@@ -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