-
Notifications
You must be signed in to change notification settings - Fork 1
/
BinaryTree.go
183 lines (162 loc) · 3.83 KB
/
BinaryTree.go
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package trees
/*
Binary Tree Implementation
*/
type BinaryTreeNode struct {
value interface{}
Left, Right *BinaryTreeNode
}
func NewBinaryTreeNode(value interface{}) *BinaryTreeNode {
return &BinaryTreeNode{
value: value,
Left: nil,
Right: nil,
}
}
type BinaryTree struct {
Root *BinaryTreeNode
}
func NewBinaryTree() *BinaryTree {
return &BinaryTree{Root: nil}
}
// Traverse recursively
func (bt *BinaryTree)TraversePreorder(cb func(value interface{})) {
Preorder(bt.Root, cb)
}
// Traverse iterate
func (bt *BinaryTree)TraversePreorderIter(cb func(value interface{})) {
stack := []*BinaryTreeNode{bt.Root}
for len(stack) > 0 {
node := stack[len(stack)-1]
stack = stack[:len(stack)-1]
cb(node)
// push right first and then left so left will be popped up first
if node.Right != nil {
stack = append(stack, node.Right)
}
if node.Left != nil {
stack = append(stack, node.Left)
}
}
}
func Preorder(node *BinaryTreeNode, cb func(value interface{})) {
if node == nil {
return
}
cb(node.value)
Preorder(node.Left, cb)
Preorder(node.Right, cb)
}
// Traverse recursively
func (bt *BinaryTree)TraverseInorder(cb func(value interface{})) {
Inorder(bt.Root, cb)
}
func Inorder(node *BinaryTreeNode, cb func(value interface{})) {
if node == nil {
return
}
Preorder(node.Left, cb)
cb(node.value)
Preorder(node.Right, cb)
}
// Traverse iterate
func (bt *BinaryTree)TraverseInorderIter(cb func(value interface{})) {
// Start at root
curr := bt.Root
stack := []*BinaryTreeNode{}
done := false
for !done {
if curr != nil {
// push root into stack
stack = append(stack, curr)
// Traverse left until we have no left trees left
curr = curr.Left
} else {
// As long as we have elements in the stack
if len(stack) > 0 {
// Pop the last stack element pushed.
node := stack[len(stack)-1]
stack = stack[:len(stack)-1]
// Inorder callback
cb(node.value)
// Traverse Right now
node = node.Right
} else {
done = true
}
}
}
}
// Traverse recursively
func (bt *BinaryTree)TraversePostorder(cb func(value interface{})) {
Postorder(bt.Root, cb)
}
func Postorder(node *BinaryTreeNode, cb func(value interface{})) {
if node == nil {
return
}
Preorder(node.Left, cb)
Preorder(node.Right, cb)
cb(node.value)
}
// Traverse iterate
func (bt *BinaryTree)TraversePostorderIter(cb func(value interface{})) {
// Create two stacks
s1 := []*BinaryTreeNode{}
s2 := []*BinaryTreeNode{}
// Push root to first stack
s1 = append(s1, bt.Root)
// Run while first stack is not empty
for len(s1) > 0 {
// Pop an item from s1 and append it to s2
node := s1[len(s1)-1]
s1 = s1[:len(s1)-1]
s2 = append(s2, node)
// Push left and right children of removed item to s1
if node.Left != nil {
s1 = append(s1, node.Left)
}
if node.Right != nil {
s1 = append(s1, node.Right)
}
}
// Print all elements of second stack
for len(s2) > 0 {
node := s2[len(s2)-1]
s2 = s2[:len(s2)-1]
cb(node.value)
}
}
type NodeLevel struct {
Node *BinaryTreeNode
Level int
}
// Traverse recursively
func (bt *BinaryTree)TraverseLevelorder() [][]int {
result := [][]int{}
level := 0
// Use a queue as FIFO access
queue := []NodeLevel{}
if bt.Root == nil {
return result
}
queue = append(queue, NodeLevel{Node:bt.Root, Level:level})
result = append(result, []int{})
for len(queue) > 0 {
// Grab first element
curr, rest := queue[0], queue[1:]
queue = rest
if len(result)-1 < curr.Level {
result = append(result, []int{})
}
result[curr.Level] = append(result[curr.Level], curr.Node.value.(int))
// Push left and right children into the queue
if curr.Node.Left != nil {
queue = append(queue, NodeLevel{Node:curr.Node.Left, Level:curr.Level+1})
}
if curr.Node.Right != nil {
queue = append(queue, NodeLevel{Node:curr.Node.Right, Level:curr.Level+1})
}
}
return result
}