-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtree_traversal.py
151 lines (104 loc) · 3.42 KB
/
tree_traversal.py
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
from collections import deque
class Tree(object):
class Node(object):
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def __init__(self):
self.root = None
def insert(self, data, node=None):
def _rec_insert(node, data):
# recursively insert
if not node:
return self.Node(data)
if data > node.data:
node.right = _rec_insert(node.right, data)
else:
node.left = _rec_insert(node.left, data)
return node
if not self.root:
# First node
self.root = self.Node(data)
else:
# Remaining inserts
self.root = _rec_insert(self.root, data)
return self.root
def pre_order(self):
""" a.k.a DFS (depth first search) """
queue = []
def _rec_pre_order(node):
if not node: return
queue.append(node.data)
_rec_pre_order(node.left)
_rec_pre_order(node.right)
return queue
return _rec_pre_order(self.root)
def in_order(self):
queue = []
def _rec_in_order(node):
if not node: return
_rec_in_order(node.left)
queue.append(node.data)
_rec_in_order(node.right)
return queue
return _rec_in_order(self.root)
def post_order(self):
queue = []
def _rec_post_order(node):
if not node: return
_rec_post_order(node.left)
_rec_post_order(node.right)
queue.append(node.data)
return queue
return _rec_post_order(self.root)
def level_order(self):
""" a.k.a BFS (breadth first search) """
queue = deque([self.root])
while queue:
node = queue.popleft()
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
yield node.data
def size(self):
def count(node):
if not node: return 0
return 1 + count(node.left) + count(node.right)
return count(self.root)
def max_depth(self):
paths = []
def all_paths(node, path=[]):
if not node: return
path = path + [node.data]
if not node.left and not node.right:
paths.append(path)
all_paths(node.left, path)
all_paths(node.right, path)
all_paths(self.root)
return len(max(paths, key=len))
def is_balanced(self):
def height(node):
if not node: return (True, 0)
left_height = height(node.left)
right_height = height(node.right)
_is_balanced = abs(right_height[1] - left_height[1]) <= 1
tree_height = max(left_height[1], right_height[1]) + 1
return (_is_balanced, tree_height)
return height(self.root)[0]
tree = Tree()
tree.insert(5)
tree.insert(4)
tree.insert(7)
tree.insert(3)
tree.insert(6)
tree.insert(2)
tree.insert(9)
print("Level order ->", [node for node in tree.level_order()])
print("Pre order ->", tree.pre_order())
print("Inorder (sorted) ->", tree.in_order())
print("Post order->", tree.post_order())
print("Size ->", tree.size())
print("Max depth ->", tree.max_depth())
print("Is balanced ->", tree.is_balanced())