ds 0.0.4 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rubocop.yml +11 -0
- data/.rubocop_todo.yml +452 -0
- data/.travis.yml +12 -0
- data/Gemfile +1 -1
- data/README.rdoc +185 -214
- data/Rakefile +8 -3
- data/ds.gemspec +16 -13
- data/lib/ds.rb +20 -30
- data/lib/ds/{matrixes → arrays}/array_2d.rb +9 -10
- data/lib/ds/arrays/expandable_array.rb +34 -0
- data/lib/ds/arrays/heap_store.rb +32 -0
- data/lib/ds/arrays/tri_matrix.rb +33 -0
- data/lib/ds/lists/list.rb +310 -186
- data/lib/ds/lists/list_element.rb +14 -11
- data/lib/ds/pair.rb +4 -4
- data/lib/ds/queues/priority_queue.rb +33 -20
- data/lib/ds/queues/simple_queue.rb +55 -0
- data/lib/ds/sets/indexed_set.rb +37 -0
- data/lib/ds/stacks/stack.rb +25 -17
- data/lib/ds/trees/binary_heap.rb +71 -66
- data/lib/ds/trees/binary_tree.rb +40 -44
- data/lib/ds/trees/red_black_tree.rb +123 -0
- data/lib/ds/trees/red_black_tree/node.rb +21 -0
- data/lib/ds/trees/tree.rb +50 -48
- data/lib/ds/trees/tree_walker.rb +73 -144
- data/lib/ds/trees/trie.rb +67 -37
- data/lib/ds/trees/trie/node.rb +48 -0
- data/lib/ds/version.rb +2 -1
- data/test/help.rb +3 -6
- data/test/performance/binary_heap_performance_test.rb +20 -0
- data/test/performance/list_performance_test.rb +36 -0
- data/test/performance/priority_queue_performance.rb +32 -0
- data/test/performance/rbt_performance_test.rb +17 -0
- data/test/performance/simple_queue_performance_test.rb +37 -0
- data/test/performance/stack_test.rb +45 -0
- data/test/test_array2d.rb +29 -31
- data/test/test_binary_heap.rb +29 -23
- data/test/test_binary_tree.rb +30 -20
- data/test/test_expandable_array.rb +6 -10
- data/test/test_heap_store.rb +34 -0
- data/test/test_indexed_set.rb +26 -0
- data/test/test_list.rb +226 -109
- data/test/test_list_element.rb +34 -16
- data/test/test_pair.rb +5 -8
- data/test/test_priority_queue.rb +43 -64
- data/test/test_queue.rb +12 -61
- data/test/test_red_black_tree.rb +46 -0
- data/test/test_stack.rb +35 -39
- data/test/test_tree.rb +42 -29
- data/test/test_tree_walker.rb +27 -52
- data/test/test_tri_matrix.rb +6 -11
- data/test/test_trie.rb +59 -17
- metadata +80 -35
- data/lib/ds/ext/array_x.rb +0 -35
- data/lib/ds/graphs/digraph.rb +0 -20
- data/lib/ds/graphs/edge.rb +0 -15
- data/lib/ds/graphs/graph.rb +0 -111
- data/lib/ds/graphs/graph_as_matrix.rb +0 -113
- data/lib/ds/graphs/graph_as_tri_matrix.rb +0 -24
- data/lib/ds/lists/cyclic_list.rb +0 -21
- data/lib/ds/lists/ring.rb +0 -42
- data/lib/ds/matrixes/expandable_array.rb +0 -37
- data/lib/ds/matrixes/tri_matrix.rb +0 -30
- data/lib/ds/queues/queue.rb +0 -53
- data/lib/ds/sets/ordered_set.rb +0 -32
- data/lib/ds/trees/binary_search_tree.rb +0 -34
- data/lib/ds/trees/complete_binary_tree.rb +0 -60
- data/test/test_array_x.rb +0 -51
- data/test/test_binary_search_tree.rb +0 -39
- data/test/test_complete_binary_tree.rb +0 -58
- data/test/test_digraph.rb +0 -134
- data/test/test_graph.rb +0 -80
- data/test/test_ordered_set.rb +0 -28
- data/test/test_ring.rb +0 -28
data/lib/ds/trees/binary_tree.rb
CHANGED
@@ -1,71 +1,67 @@
|
|
1
1
|
module DS
|
2
|
+
# Class implements binary tree
|
2
3
|
class BinaryTree < Tree
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
subtree = BinaryTree.new(value)
|
4
|
+
# Inserts a new subtree.
|
5
|
+
def <<(value)
|
6
|
+
subtree = BinaryTree.new(value, self)
|
7
7
|
@children << subtree
|
8
|
-
|
8
|
+
subtree
|
9
9
|
end
|
10
10
|
|
11
|
-
#Returns left subtree
|
11
|
+
# Returns left subtree
|
12
12
|
def left
|
13
|
-
|
14
|
-
nil
|
15
|
-
else
|
16
|
-
@children[0]
|
17
|
-
end
|
13
|
+
@children[0]
|
18
14
|
end
|
19
15
|
|
20
|
-
#Sets left subtree
|
16
|
+
# Sets left subtree
|
21
17
|
def left=(value)
|
22
18
|
@children[0] = value
|
23
19
|
end
|
24
20
|
|
25
|
-
#Returns right subtree
|
21
|
+
# Returns right subtree
|
26
22
|
def right
|
27
|
-
|
28
|
-
nil
|
29
|
-
else
|
30
|
-
@children[1]
|
31
|
-
end
|
23
|
+
@children[1]
|
32
24
|
end
|
33
25
|
|
34
|
-
#Sets right subtree
|
26
|
+
# Sets right subtree
|
35
27
|
def right=(value)
|
36
28
|
@children[1] = value
|
37
29
|
end
|
38
30
|
|
39
|
-
|
40
|
-
#Inserts new element in BSF order
|
31
|
+
# Inserts new element in BSF order
|
41
32
|
def insert(x)
|
42
|
-
q =
|
43
|
-
if @data
|
33
|
+
q = SimpleQueue.new
|
34
|
+
if @data.nil?
|
44
35
|
@data = x
|
45
|
-
elsif
|
46
|
-
self.left = BinaryTree.new(x)
|
47
|
-
elsif
|
48
|
-
self.right = BinaryTree.new(x)
|
36
|
+
elsif left.nil?
|
37
|
+
self.left = BinaryTree.new(x, self)
|
38
|
+
elsif right.nil?
|
39
|
+
self.right = BinaryTree.new(x, self)
|
49
40
|
else
|
50
|
-
q.push
|
51
|
-
q.push
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
41
|
+
q.push left
|
42
|
+
q.push right
|
43
|
+
insert_next(q, x)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def insert_next(q, x)
|
50
|
+
loop do
|
51
|
+
node = q.shift
|
52
|
+
if node.left.nil?
|
53
|
+
node.insert(x)
|
54
|
+
break
|
55
|
+
else
|
56
|
+
q.push node.left
|
57
|
+
end
|
58
|
+
if node.right.nil?
|
59
|
+
node.insert(x)
|
60
|
+
break
|
61
|
+
else
|
62
|
+
q.push node.right
|
66
63
|
end
|
67
64
|
end
|
68
65
|
end
|
69
66
|
end
|
70
67
|
end
|
71
|
-
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module DS
|
2
|
+
# Class implements Red Black Tree
|
3
|
+
class RedBlackTree
|
4
|
+
RED = true
|
5
|
+
BLACK = false
|
6
|
+
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
attr_accessor :root
|
10
|
+
attr_reader :size
|
11
|
+
|
12
|
+
def initialize(hash = nil)
|
13
|
+
@root = nil
|
14
|
+
@size = 0
|
15
|
+
@iterator = TreeWalker.new(root)
|
16
|
+
hash.each { |k, v| insert(k, v) } if hash
|
17
|
+
end
|
18
|
+
|
19
|
+
def insert(key, value)
|
20
|
+
self.root = put(root, key, value)
|
21
|
+
root.color = BLACK
|
22
|
+
end
|
23
|
+
|
24
|
+
def []=(key, value)
|
25
|
+
insert(key, value)
|
26
|
+
end
|
27
|
+
|
28
|
+
def get(key, node = root)
|
29
|
+
x = node
|
30
|
+
while x
|
31
|
+
case key <=> x.key
|
32
|
+
when -1
|
33
|
+
x = x.left
|
34
|
+
when 1
|
35
|
+
x = x.right
|
36
|
+
else
|
37
|
+
return x.data
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def [](key)
|
43
|
+
get(key)
|
44
|
+
end
|
45
|
+
|
46
|
+
def each
|
47
|
+
iterator = TreeWalker.new(root)
|
48
|
+
iterator.traverse(:inorder) { |t| yield t }
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_h
|
52
|
+
each_with_object({}) { |n, h| h[n.key] = n.data }
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def put(n, key, value)
|
58
|
+
if n.nil?
|
59
|
+
@size += 1
|
60
|
+
return Node.new(key, value, RED)
|
61
|
+
end
|
62
|
+
|
63
|
+
case key <=> n.key
|
64
|
+
when -1
|
65
|
+
n.left = put(n.left, key, value)
|
66
|
+
when 1
|
67
|
+
n.right = put(n.right, key, value)
|
68
|
+
else
|
69
|
+
n.data = value
|
70
|
+
end
|
71
|
+
|
72
|
+
balance(n)
|
73
|
+
end
|
74
|
+
|
75
|
+
def balance(n)
|
76
|
+
n = rotate_left(n) if right_red?(n)
|
77
|
+
n = rotate_right(n) if two_red_in_row?(n)
|
78
|
+
flip_colors(n) if red_children?(n)
|
79
|
+
n
|
80
|
+
end
|
81
|
+
|
82
|
+
def red_children?(n)
|
83
|
+
red?(n.left) && red?(n.right)
|
84
|
+
end
|
85
|
+
|
86
|
+
def two_red_in_row?(n)
|
87
|
+
red?(n.left) && red?(n.left.left)
|
88
|
+
end
|
89
|
+
|
90
|
+
def right_red?(n)
|
91
|
+
red?(n.right) && !red?(n.left)
|
92
|
+
end
|
93
|
+
|
94
|
+
def red?(n)
|
95
|
+
return false if n.nil?
|
96
|
+
n.color == RED
|
97
|
+
end
|
98
|
+
|
99
|
+
def rotate_left(n)
|
100
|
+
x = n.right
|
101
|
+
n.right = x.left
|
102
|
+
x.left = n
|
103
|
+
x.color = n.color
|
104
|
+
n.color = RED
|
105
|
+
x
|
106
|
+
end
|
107
|
+
|
108
|
+
def rotate_right(n)
|
109
|
+
x = n.left
|
110
|
+
n.left = x.right
|
111
|
+
x.right = n
|
112
|
+
x.color = n.color
|
113
|
+
n.color = RED
|
114
|
+
x
|
115
|
+
end
|
116
|
+
|
117
|
+
def flip_colors(n)
|
118
|
+
n.color = RED
|
119
|
+
n.left.color = BLACK
|
120
|
+
n.right.color = BLACK
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module DS
|
2
|
+
# Class implements Red Black Tree
|
3
|
+
class RedBlackTree
|
4
|
+
# Red Black Tree Node
|
5
|
+
class Node
|
6
|
+
attr_accessor :color, :right, :left, :data, :key
|
7
|
+
|
8
|
+
def initialize(key, value, color)
|
9
|
+
@key = key
|
10
|
+
@data = value
|
11
|
+
@color = color
|
12
|
+
@left = nil
|
13
|
+
@right = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def children
|
17
|
+
[@left, @right]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/ds/trees/tree.rb
CHANGED
@@ -1,55 +1,59 @@
|
|
1
1
|
module DS
|
2
|
+
# Tree class
|
2
3
|
class Tree
|
3
|
-
|
4
4
|
include Enumerable
|
5
5
|
|
6
6
|
attr_accessor :data
|
7
|
-
attr_reader :children
|
7
|
+
attr_reader :children, :parent
|
8
8
|
|
9
|
-
#Returns a new tree.
|
10
|
-
def initialize(value=nil)
|
9
|
+
# Returns a new tree.
|
10
|
+
def initialize(value = nil, parent = nil)
|
11
11
|
@data = value
|
12
|
+
@parent = parent
|
12
13
|
@children = []
|
13
14
|
end
|
14
15
|
|
15
|
-
#Inserts a new subtree.
|
16
|
-
def <<
|
17
|
-
subtree = Tree.new(value)
|
16
|
+
# Inserts a new subtree.
|
17
|
+
def <<(value)
|
18
|
+
subtree = Tree.new(value, self)
|
18
19
|
@children << subtree
|
19
|
-
|
20
|
+
subtree
|
21
|
+
end
|
22
|
+
|
23
|
+
def sibblings
|
24
|
+
parent.children.reject { |node| node == self }
|
20
25
|
end
|
21
26
|
|
22
|
-
#Checks if node is leaf.
|
27
|
+
# Checks if node is leaf.
|
23
28
|
def leaf?
|
24
|
-
|
29
|
+
children.empty?
|
25
30
|
end
|
26
31
|
|
27
|
-
#Returns leaf list.
|
28
|
-
def get_leaves(tree=self)
|
32
|
+
# Returns leaf list.
|
33
|
+
def get_leaves(tree = self)
|
29
34
|
list = List.new
|
30
|
-
walker = TreeWalker.new(
|
31
|
-
walker.traverse
|
35
|
+
walker = TreeWalker.new(tree, order: :postorder)
|
36
|
+
walker.traverse { |t| list.append(t) if t.leaf? }
|
32
37
|
list
|
33
38
|
end
|
34
39
|
|
35
|
-
#Returns the number of leaves for given subtree.
|
36
|
-
def leaf_count(tree=self)
|
40
|
+
# Returns the number of leaves for given subtree.
|
41
|
+
def leaf_count(tree = self)
|
37
42
|
if tree.leaf?
|
38
43
|
1
|
39
44
|
else
|
40
|
-
tree.children.inject(0){|
|
45
|
+
tree.children.inject(0) { |a, e| a + leaf_count(e) }
|
41
46
|
end
|
42
47
|
end
|
43
48
|
|
44
|
-
|
45
|
-
#
|
46
|
-
#{1=>1, 2=>4, 3=>5}
|
49
|
+
# Returns number of nodes for each tree level.
|
50
|
+
# {1=>1, 2=>4, 3=>5}
|
47
51
|
def levels
|
48
52
|
walker = TreeWalker.new(self)
|
49
|
-
nodes={}
|
53
|
+
nodes = {}
|
50
54
|
|
51
|
-
walker.traverse_with_h(self,1) do |
|
52
|
-
if nodes[level]
|
55
|
+
walker.traverse_with_h(self, 1) do |_t, level|
|
56
|
+
if nodes[level]
|
53
57
|
nodes[level] += 1
|
54
58
|
else
|
55
59
|
nodes[level] = 1
|
@@ -58,60 +62,58 @@ module DS
|
|
58
62
|
nodes
|
59
63
|
end
|
60
64
|
|
61
|
-
#Returns tree width.
|
65
|
+
# Returns tree width.
|
62
66
|
def width
|
63
|
-
|
67
|
+
levels.values.max
|
64
68
|
end
|
65
|
-
|
66
|
-
#Returns subtree height.
|
69
|
+
|
70
|
+
# Returns subtree height.
|
67
71
|
def self.h(tree)
|
68
|
-
|
69
|
-
tree.children.map{|t| h(t) }.max + 1
|
70
|
-
else
|
72
|
+
if tree.leaf?
|
71
73
|
1
|
74
|
+
else
|
75
|
+
tree.children.map { |t| h(t) }.max + 1
|
72
76
|
end
|
73
77
|
end
|
74
78
|
|
75
|
-
#Returns tree height.
|
79
|
+
# Returns tree height.
|
76
80
|
def height
|
77
81
|
Tree.h(self)
|
78
82
|
end
|
79
83
|
|
80
|
-
#Returns node which lies closest to the root.
|
84
|
+
# Returns node which lies closest to the root.
|
81
85
|
def lowest_height
|
82
|
-
find
|
86
|
+
find(&:leaf?)
|
83
87
|
end
|
84
88
|
|
85
|
-
#Mirrors tree.
|
86
|
-
def mirror!(tree=self)
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
end
|
89
|
+
# Mirrors tree.
|
90
|
+
def mirror!(tree = self)
|
91
|
+
return if tree.leaf?
|
92
|
+
tree.children.reverse!
|
93
|
+
tree.children.each { |t| mirror!(t) }
|
91
94
|
end
|
92
95
|
|
93
|
-
#Checks if tree is isometric to another tree.
|
96
|
+
# Checks if tree is isometric to another tree.
|
94
97
|
def izometric?(other)
|
95
98
|
tree = self
|
96
|
-
unless tree.leaf?
|
99
|
+
unless tree.leaf? && other.leaf?
|
97
100
|
if tree.children.size == other.children.size
|
98
|
-
tree.children.each_with_index{|t,i| return false unless t.izometric?(other.children[i])}
|
101
|
+
tree.children.each_with_index { |t, i| return false unless t.izometric?(other.children[i]) }
|
99
102
|
else
|
100
103
|
return false
|
101
104
|
end
|
102
105
|
end
|
103
|
-
|
106
|
+
true
|
104
107
|
end
|
105
108
|
|
106
|
-
|
107
|
-
#Iterates tree in BFS order.
|
109
|
+
# Iterates tree in BFS order.
|
108
110
|
def each
|
109
|
-
TreeWalker.new(self)
|
111
|
+
iterator = TreeWalker.new(self)
|
112
|
+
iterator.traverse { |t| yield t }
|
110
113
|
end
|
111
114
|
|
112
115
|
def to_a
|
113
|
-
map
|
116
|
+
map(&:data)
|
114
117
|
end
|
115
118
|
end
|
116
119
|
end
|
117
|
-
|
data/lib/ds/trees/tree_walker.rb
CHANGED
@@ -1,180 +1,109 @@
|
|
1
1
|
module DS
|
2
|
+
# Tree enumerator
|
2
3
|
class TreeWalker
|
4
|
+
attr_accessor :visited, :tree, :action, :order
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
#Creates new tree iterator.
|
9
|
-
def initialize(tree=nil)
|
10
|
-
@visited = []
|
6
|
+
# Creates new tree iterator.
|
7
|
+
def initialize(tree, options = {}, &block)
|
8
|
+
@visited = []
|
11
9
|
@tree = tree
|
10
|
+
@order = options[:order] || :bfs
|
11
|
+
@action = block
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#inorder - inorder search - only for Binary Trees
|
14
|
+
# Traversing tree in given order:
|
15
|
+
# bfs - Breadth-first search - default
|
16
|
+
# postorder - postorder search
|
17
|
+
# preorder - preorder search
|
18
|
+
# inorder - inorder search - only for Binary Trees
|
20
19
|
#
|
21
|
-
#If block is given, passes each visited subtree to block.
|
22
|
-
#Returns values of nodes
|
23
|
-
|
24
|
-
def traverse(
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
traverse_bfs
|
31
|
-
|
32
|
-
walk(tree
|
33
|
-
when :preorder
|
34
|
-
walk(tree,:preorder, &block)
|
35
|
-
when :inorder
|
36
|
-
raise ArgumentError unless tree.kind_of? BinaryTree
|
37
|
-
walk(tree,order,&block)
|
20
|
+
# If block is given, passes each visited subtree to block.
|
21
|
+
# Returns values of nodes in given order
|
22
|
+
|
23
|
+
def traverse(traverse_order = nil, &block)
|
24
|
+
self.action = block if block_given?
|
25
|
+
self.order = traverse_order if traverse_order
|
26
|
+
reset!
|
27
|
+
|
28
|
+
if order == :bfs
|
29
|
+
traverse_bfs
|
30
|
+
else
|
31
|
+
walk(tree)
|
38
32
|
end
|
39
|
-
|
40
|
-
return visited
|
33
|
+
visited
|
41
34
|
end
|
42
35
|
|
43
|
-
#Traverses tree in BFS order.
|
44
|
-
def traverse_bfs
|
45
|
-
|
46
|
-
q.
|
47
|
-
|
36
|
+
# Traverses tree in BFS order.
|
37
|
+
def traverse_bfs(&block)
|
38
|
+
self.action = block if block_given?
|
39
|
+
q = SimpleQueue.new
|
40
|
+
q.push tree
|
41
|
+
|
48
42
|
loop do
|
49
43
|
break if q.empty?
|
50
44
|
node = q.shift
|
51
|
-
|
52
|
-
|
53
|
-
else
|
54
|
-
@visited << node.data
|
55
|
-
end
|
56
|
-
node.children.each{ |n| q.push n } if node.children
|
45
|
+
visit_node(node)
|
46
|
+
node.children.each { |n| q.push n } if node.children
|
57
47
|
end
|
58
48
|
end
|
59
49
|
|
60
|
-
#Resets tree walker.
|
61
|
-
def reset
|
50
|
+
# Resets tree walker.
|
51
|
+
def reset!
|
62
52
|
@visited.clear
|
63
53
|
self
|
64
54
|
end
|
65
55
|
|
66
|
-
|
67
|
-
|
68
|
-
#Traverses tree with tracking level.
|
69
|
-
def traverse_with_h(tree,height=nil,&block)
|
70
|
-
|
56
|
+
# Traverses tree with tracking level.
|
57
|
+
def traverse_with_h(tree, height = nil, &block)
|
71
58
|
tree.children.each do |t|
|
72
|
-
traverse_with_h(t,height+1
|
73
|
-
end
|
74
|
-
|
75
|
-
if block_given?
|
76
|
-
yield tree, height
|
59
|
+
traverse_with_h(t, height + 1, &block)
|
77
60
|
end
|
78
61
|
|
62
|
+
yield tree, height if block_given?
|
79
63
|
end
|
80
64
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
tree.data = result
|
92
|
-
|
93
|
-
|
94
|
-
when :preorder
|
95
|
-
|
96
|
-
tree.data = yield tree, memo
|
97
|
-
memo = tree.data
|
98
|
-
|
99
|
-
tree.children.each do |t|
|
100
|
-
recalculate!(t,order,memo,&block)
|
101
|
-
end
|
102
|
-
|
103
|
-
when :inorder
|
104
|
-
raise ArgumentError unless self.tree.is_a? BinaryTree
|
105
|
-
recalculate!(tree.left,order,memo,&block)
|
106
|
-
|
107
|
-
tree.data = yield tree, memo
|
108
|
-
memo = tree.data
|
109
|
-
|
110
|
-
recalculate!(tree.right,order,memo,&block)
|
111
|
-
|
65
|
+
# Recalculates tree by evaluating block on every node.
|
66
|
+
def recalculate!(tree, order, memo = nil, &block)
|
67
|
+
case order
|
68
|
+
when :postorder
|
69
|
+
arr = tree.children.map { |t| recalculate!(t, order, memo, &block) }
|
70
|
+
tree.data = yield tree, arr
|
71
|
+
when :preorder
|
72
|
+
tree.data = yield tree, memo
|
73
|
+
tree.children.each do |t|
|
74
|
+
recalculate!(t, order, tree.data, &block)
|
112
75
|
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
|
117
|
-
#Summarize tree
|
118
|
-
def summarize(direction=:bottomup)
|
119
|
-
|
120
|
-
case direction
|
121
|
-
when :bottomup
|
122
|
-
recalculate!(self.tree,:postorder,0){|ar| ar.inject(0){|x,memo| memo += x}}
|
123
|
-
self.tree
|
124
|
-
when :topdown
|
125
|
-
recalculate!(self.tree,:preorder,0){|x,memo| memo = memo+x.data}
|
126
|
-
self.tree
|
127
76
|
when :inorder
|
128
|
-
recalculate!(
|
129
|
-
|
130
|
-
|
77
|
+
recalculate!(tree.left, order, memo, &block)
|
78
|
+
tree.data = yield tree, memo
|
79
|
+
recalculate!(tree.right, order, tree.data, &block)
|
80
|
+
end if tree
|
131
81
|
end
|
132
82
|
|
133
|
-
|
134
|
-
|
135
83
|
private
|
136
84
|
|
137
|
-
def
|
138
|
-
if
|
139
|
-
|
140
|
-
|
141
|
-
when :postorder
|
142
|
-
tree.children.each do |t|
|
143
|
-
walk(t,order,&block)
|
144
|
-
end
|
145
|
-
|
146
|
-
if block_given?
|
147
|
-
yield tree
|
148
|
-
else
|
149
|
-
@visited << tree.data
|
150
|
-
end
|
151
|
-
|
152
|
-
when :preorder
|
153
|
-
if block_given?
|
154
|
-
yield tree
|
155
|
-
else
|
156
|
-
@visited << tree.data
|
157
|
-
end
|
158
|
-
|
159
|
-
tree.children.each do |t|
|
160
|
-
walk(t,order,&block)
|
161
|
-
end
|
162
|
-
|
163
|
-
when :inorder
|
164
|
-
raise ArgumentError unless self.tree.is_a? BinaryTree
|
165
|
-
walk(tree.left,order,&block)
|
166
|
-
|
167
|
-
if block_given?
|
168
|
-
yield tree
|
169
|
-
else
|
170
|
-
@visited << tree.data
|
171
|
-
end
|
85
|
+
def visit_node(node)
|
86
|
+
action.call(node) if action
|
87
|
+
@visited << node.data
|
88
|
+
end
|
172
89
|
|
173
|
-
|
90
|
+
def visit_children(node)
|
91
|
+
node.children.each { |t| walk(t) }
|
92
|
+
end
|
174
93
|
|
175
|
-
|
176
|
-
|
94
|
+
def walk(node)
|
95
|
+
case order
|
96
|
+
when :postorder
|
97
|
+
visit_children(node)
|
98
|
+
visit_node(node)
|
99
|
+
when :preorder
|
100
|
+
visit_node(node)
|
101
|
+
visit_children(node)
|
102
|
+
when :inorder
|
103
|
+
walk(node.left)
|
104
|
+
visit_node(node)
|
105
|
+
walk(node.right)
|
106
|
+
end if node
|
177
107
|
end
|
178
108
|
end
|
179
109
|
end
|
180
|
-
|