avl_tree 1.1.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,4 @@
1
1
  require 'benchmark'
2
- require 'radix_tree' # gem install radix_tree
3
2
  require 'avl_tree'
4
3
  require 'red_black_tree'
5
4
  require 'openssl'
@@ -47,7 +46,6 @@ end
47
46
 
48
47
  Benchmark.bmbm do |bm|
49
48
  run(bm, Hash.new, keys)
50
- run(bm, RadixTree.new, keys)
51
49
  run(bm, AVLTree.new, keys)
52
50
  run(bm, RedBlackTree.new, keys)
53
51
  end
@@ -4,65 +4,6 @@ class AVLTree
4
4
  class Node
5
5
  UNDEFINED = Object.new
6
6
 
7
- class EmptyNode
8
- def empty?
9
- true
10
- end
11
-
12
- def height
13
- 0
14
- end
15
-
16
- def value
17
- nil
18
- end
19
-
20
- def size
21
- 0
22
- end
23
-
24
- def each(&block)
25
- # intentionally blank
26
- end
27
-
28
- # returns new_root
29
- def insert(key, value)
30
- Node.new(key, value)
31
- end
32
-
33
- # returns value
34
- def retrieve(key)
35
- UNDEFINED
36
- end
37
-
38
- # returns [deleted_node, new_root]
39
- def delete(key)
40
- [self, self]
41
- end
42
-
43
- def dump_tree(io, indent = '')
44
- # intentionally blank
45
- end
46
-
47
- def dump_sexp
48
- # intentionally blank
49
- end
50
-
51
- def rotate
52
- self
53
- end
54
-
55
- def update_height
56
- # intentionally blank
57
- end
58
-
59
- # for debugging
60
- def check_height
61
- # intentionally blank
62
- end
63
- end
64
- EMPTY = Node::EmptyNode.new
65
-
66
7
  attr_reader :key, :value, :height
67
8
  attr_reader :left, :right
68
9
 
@@ -285,6 +226,63 @@ class AVLTree
285
226
  end
286
227
  pool
287
228
  end
229
+
230
+ class EmptyNode < Node
231
+ def initialize
232
+ @value = nil
233
+ @height = 0
234
+ end
235
+
236
+ def empty?
237
+ true
238
+ end
239
+
240
+ def size
241
+ 0
242
+ end
243
+
244
+ def each(&block)
245
+ # intentionally blank
246
+ end
247
+
248
+ # returns new_root
249
+ def insert(key, value)
250
+ Node.new(key, value)
251
+ end
252
+
253
+ # returns value
254
+ def retrieve(key)
255
+ UNDEFINED
256
+ end
257
+
258
+ # returns [deleted_node, new_root]
259
+ def delete(key)
260
+ [self, self]
261
+ end
262
+
263
+ def dump_tree(io, indent = '')
264
+ # intentionally blank
265
+ end
266
+
267
+ def dump_sexp
268
+ # intentionally blank
269
+ end
270
+
271
+ def rotate
272
+ self
273
+ end
274
+
275
+ def update_height
276
+ # intentionally blank
277
+ end
278
+
279
+ # for debugging
280
+ def check_height
281
+ # intentionally blank
282
+ end
283
+ end
284
+ EMPTY = Node::EmptyNode.new.freeze
285
+
288
286
  end
289
287
 
290
288
  DEFAULT = Object.new
@@ -67,18 +67,18 @@ class RedBlackTree
67
67
  case key <=> @key
68
68
  when -1
69
69
  @left = @left.insert(key, value)
70
- if black? and @left.red? and !@left.children_both_black?
70
+ if black? and @right.black? and @left.red? and !@left.children_both_black?
71
71
  ret = rebalance_for_left_insert
72
72
  end
73
73
  when 0
74
74
  @value = value
75
75
  when 1
76
76
  @right = @right.insert(key, value)
77
- if black? and @right.red? and !@right.children_both_black?
77
+ if black? and @left.black? and @right.red? and !@right.children_both_black?
78
78
  ret = rebalance_for_right_insert
79
79
  end
80
80
  end
81
- ret
81
+ ret.pullup_red
82
82
  end
83
83
 
84
84
  # returns value
@@ -304,40 +304,40 @@ class RedBlackTree
304
304
  root
305
305
  end
306
306
 
307
+ # Pull up red nodes
308
+ # (b (A C)) where A and C are RED --> (B (a c))
309
+ #
310
+ # b B
311
+ # / \ -> / \
312
+ # A C a c
313
+ #
314
+ def pullup_red
315
+ if black? and @left.red? and @right.red?
316
+ @left.color = @right.color = :BLACK
317
+ self.color = :RED
318
+ end
319
+ self
320
+ end
321
+
307
322
  private
308
323
 
309
324
  # trying to rebalance when the left sub-tree is 1 level higher than the right
310
325
  # precondition: self is black and @left is red
311
326
  def rebalance_for_left_insert
312
- ret = self
313
- if @right.red?
314
- # pull-up red nodes and let the parent rebalance (see precondition)
315
- @color = :RED
316
- @left.color = @right.color = :BLACK
317
- else
318
- # move 1 black from the left to the right by single/double rotation
319
- if @left.right.red?
320
- @left = @left.rotate_left
321
- end
322
- ret = rotate_right
327
+ # move 1 black from the left to the right by single/double rotation
328
+ if @left.right.red?
329
+ @left = @left.rotate_left
323
330
  end
324
- ret
331
+ rotate_right
325
332
  end
326
333
 
327
334
  # trying to rebalance when the right sub-tree is 1 level higher than the left
328
335
  # See rebalance_for_left_insert.
329
336
  def rebalance_for_right_insert
330
- ret = self
331
- if @left.red?
332
- @color = :RED
333
- @left.color = @right.color = :BLACK
334
- else
335
- if @right.left.red?
336
- @right = @right.rotate_right
337
- end
338
- ret = rotate_left
337
+ if @right.left.red?
338
+ @right = @right.rotate_right
339
339
  end
340
- ret
340
+ rotate_left
341
341
  end
342
342
 
343
343
  def delete_self
@@ -377,23 +377,16 @@ class RedBlackTree
377
377
  pool
378
378
  end
379
379
 
380
- class EmptyNode
381
- def red?
382
- false
383
- end
384
-
385
- def black?
386
- true
380
+ class EmptyNode < Node
381
+ def initialize
382
+ @value = nil
383
+ @color = :BLACK
387
384
  end
388
385
 
389
386
  def empty?
390
387
  true
391
388
  end
392
389
 
393
- def value
394
- nil
395
- end
396
-
397
390
  def size
398
391
  0
399
392
  end
@@ -425,7 +418,7 @@ class RedBlackTree
425
418
  # intentionally blank
426
419
  end
427
420
  end
428
- EMPTY = Node::EmptyNode.new
421
+ EMPTY = Node::EmptyNode.new.freeze
429
422
  end
430
423
 
431
424
  DEFAULT = Object.new
@@ -432,6 +432,12 @@ class TestAVLTree < Test::Unit::TestCase
432
432
  assert_equal [1.3, 'a' ], h.first
433
433
  end
434
434
 
435
+ def test_values_for_empty_tree
436
+ h = AVLTree.new
437
+
438
+ assert_equal [], h.values
439
+ end
440
+
435
441
  if RUBY_VERSION >= '1.9.0'
436
442
  # In contrast to RadixTree, AVLTree just uses String#<=> as-is
437
443
  def test_encoding
@@ -51,7 +51,7 @@ class TestRedBlackTree < Test::Unit::TestCase
51
51
  h['c'] = 6
52
52
  assert_equal '(b a (g (d c) h))', h.dump_sexp
53
53
  h['e'] = 6
54
- assert_equal '(b a (g (d c e) h))', h.dump_sexp
54
+ assert_equal '(d (b a c) (g e h))', h.dump_sexp
55
55
  h['f'] = 6
56
56
  assert_equal '(d (b a c) (g (e - f) h))', h.dump_sexp
57
57
  end
@@ -67,7 +67,7 @@ class TestRedBlackTree < Test::Unit::TestCase
67
67
  h['0'] = 7
68
68
  h['c'] = 8
69
69
  h['e'] = 9
70
- assert_equal '(g (b (a 0) (d c e)) (h - i))', h.dump_sexp
70
+ assert_equal '(d (b (a 0) c) (g e (h - i)))', h.dump_sexp
71
71
  h['f'] = 10
72
72
  assert_equal '(d (b (a 0) c) (g (e - f) (h - i)))', h.dump_sexp
73
73
  end
@@ -247,9 +247,9 @@ class TestRedBlackTree < Test::Unit::TestCase
247
247
  h['f'] = 8
248
248
  h['h'] = 9
249
249
  h['j'] = 10
250
- assert_equal '(c (b a) (g (e d f) (i h j)))', h.dump_sexp
250
+ assert_equal '(e (c (b a) d) (g f (i h j)))', h.dump_sexp
251
251
  h.delete('g')
252
- assert_equal '(c (b a) (h (e d f) (i - j)))', h.dump_sexp
252
+ assert_equal '(e (c (b a) d) (h f (i - j)))', h.dump_sexp
253
253
  end
254
254
 
255
255
  def test_delete_node_left
@@ -264,9 +264,9 @@ class TestRedBlackTree < Test::Unit::TestCase
264
264
  h['e'] = 8
265
265
  h['c'] = 9
266
266
  h['a'] = 10
267
- assert_equal '(h (d (b a c) (f e g)) (i - j))', h.dump_sexp
267
+ assert_equal '(f (d (b a c) e) (h g (i - j)))', h.dump_sexp
268
268
  h.delete('d')
269
- assert_equal '(h (e (b a c) (f - g)) (i - j))', h.dump_sexp
269
+ assert_equal '(f (b a (e c)) (h g (i - j)))', h.dump_sexp
270
270
  end
271
271
 
272
272
  def test_delete_root
@@ -582,6 +582,12 @@ class TestRedBlackTree < Test::Unit::TestCase
582
582
  assert_equal [1.3, 'a' ], h.first
583
583
  end
584
584
 
585
+ def test_values_for_empty_tree
586
+ h = RedBlackTree.new
587
+
588
+ assert_equal [], h.values
589
+ end
590
+
585
591
  if RUBY_VERSION >= '1.9.0'
586
592
  # In contrast to RadixTree, RedBlackTree just uses String#<=> as-is
587
593
  def test_encoding
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: avl_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-19 00:00:00.000000000 Z
12
+ date: 2012-03-27 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description:
15
15
  email: nahi@ruby-lang.org