-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinary_tree.jl
158 lines (141 loc) · 3.62 KB
/
binary_tree.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
using Printf
# TODO: Remove parent attribute
# TODO: Insert method
# TODO: BST
# TODO: Generalize as a graph?
# A binary tree node
mutable struct Node
value::Int
parent::Union{Node, Nothing}
left::Union{Node, Nothing}
right::Union{Node, Nothing}
function Node(value)
new(value, nothing, nothing, nothing)
end
function Node(value, parent::Node)
new(value, parent, nothing, nothing)
end
function Node(value, parent::Node, left::Node, right::Node)
new(value, parent, left, right)
end
end
# Automatically figure out where to put the next node so that the tree gets filled up symetrically.
#
# 1) Find the first node that has an empty left or right, by performing a breadth first search(?)
# 2) Add the node to the first missing left or right, so traversal is most important
function insert(root::Node, node::Node)
end
# The size of the tree is the total number of nodes
function size(node::Union{Node, Nothing})
node == nothing ? 0 : 1 + size(node.left) + size(node.right)
end
# Maximum depth of any leaf
function maxdepth(node::Union{Node, Nothing})
node == nothing ? 0 : 1 + max(maxdepth(node.left), maxdepth(node.right))
end
# Depth of the node, i.e. the number of nodes in between the root node and the given node
function depth(node::Union{Node, Nothing})
node == nothing && return 0
isroot(node) ? 1 : 1 + depth(node.parent)
end
# Both children in an array, not sure if this is the most useful thing, but meh
function children(node::Node)
[ node.left node.right ]
end
# Checks if node is root by seeing if the parent is nothing
function isroot(node::Node)
node.parent == nothing
end
function isleftchild(node::Node)
node.parent.left == node
end
function isrightchild(node::Node)
node.parent.right == node
end
function isleaf(node::Node)
node.left == nothing && node.right == nothing
end
# the adjacent node
function sibling(node::Node)
if isleftchild(node)
node.parent.right
elseif isrightchild(node)
node.parent.left
end
end
# Find all nodes at a given depth from the root node
function find_nodes(root::Node, atdepth)
nodes = []
if isleaf(root)
return nodes
end
traverse(root, node -> node != nothing && depth(node) == atdepth && push!(nodes, node))
nodes
end
# style=[preorder postorder inorder]
function traverse(node::Union{Node, Nothing}, f, style="preorder")
if node == nothing
return
end
if style == "preorder"
f(node)
traverse(node.left, f, style)
traverse(node.right, f, style)
elseif style == "postorder"
traverse(node.left, f, style)
traverse(node.right, f, style)
f(node)
elseif style == "inorder"
traverse(node.left, f, style)
f(node)
traverse(node.right, f, style)
end
end
# style=[preorder postorder inorder]
function print(node::Union{Node, Nothing}, style="preorder")
traverse(node, node -> @printf("%d ", node.value))
end
# print all the root-to-leaf paths
function printpaths(node::Node)
function climb(node)
if !isleaf(node)
return
end
val = []
current = node
push!(val, current.value)
while true
current = current.parent
push!(val, current.value)
if isroot(current)
break
end
end
println(reverse(val))
end
traverse(node, climb)
end
function findmaxpathsum(node::Node)
maxsum = 0
function climb(node)
if !isleaf(node)
return
end
val = []
current = node
push!(val, current.value)
while true
current = current.parent
push!(val, current.value)
if isroot(current)
break
end
end
sum = reduce(+, val)
if sum > maxsum
maxsum = sum
end
end
traverse(node, climb)
maxsum
end