ds 0.0.4 → 0.0.6
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.
- 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
|
-
|