avl_tree 1.1.1 → 1.1.2

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,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