Skip to content

Commit b485320

Browse files
committed
Rewrote the Binary Tree implementation (fully understood and heavily documented)
1 parent 8df4435 commit b485320

File tree

2 files changed

+146
-144
lines changed

2 files changed

+146
-144
lines changed

chap06_trees/tree2.py

Lines changed: 0 additions & 144 deletions
This file was deleted.

chap06_trees/tree_binarytree.py

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
from queue import Queue
2+
3+
4+
class BinaryTree:
5+
"""
6+
All the unimaginable or unintuitive parts should be attributed to the
7+
call stack (e.g. inorder -> that's why you go straight to bottom left)
8+
9+
Cheatsheet
10+
- pre_order node L R
11+
- in_order L node R
12+
- post_order L R node
13+
"""
14+
15+
def __init__(self, value):
16+
"""
17+
You don't have to put the left/right in the param list, since it is
18+
only meant for internal use only.
19+
20+
Note that every node in itself is a root node. Unless there's context,
21+
which there isn't in the recursions, the nodes aren't "left" or "right"
22+
23+
The `value` here could also be considered as (if it helps)
24+
- root lv0 root, or sub-level root
25+
- node node + node's left + node's right
26+
- parent parent + parent's left + parent's right
27+
"""
28+
self.value = value
29+
self.left = None
30+
self.right = None
31+
32+
def insert_left(self, value):
33+
"""
34+
either put the value into the slot
35+
or put the value into the slot (plus new.LR = old_LR)
36+
"""
37+
if self.left is None:
38+
self.left = BinaryTree(value)
39+
else:
40+
new_node = BinaryTree(value)
41+
new_node.left = self.left
42+
43+
self.left = new_node
44+
45+
def insert_right(self, value):
46+
"""
47+
either put the value into the slot
48+
or put the value into the slot (plus new.LR = old_LR)
49+
"""
50+
if self.right is None:
51+
self.right = BinaryTree(value)
52+
else:
53+
new_node = BinaryTree(value)
54+
new_node.right = self.right
55+
56+
self.right = new_node
57+
58+
def dfs_preorder(self):
59+
print(self.value, end=" ")
60+
61+
if self.left:
62+
self.left.dfs_preorder()
63+
64+
if self.right:
65+
self.right.dfs_preorder()
66+
67+
def dfs_inorder(self):
68+
if self.left:
69+
self.left.dfs_inorder()
70+
71+
print(self.value, end=" ")
72+
73+
if self.right:
74+
self.right.dfs_inorder()
75+
76+
def dfs_postorder(self):
77+
if self.left:
78+
self.left.dfs_postorder()
79+
80+
if self.right:
81+
self.right.dfs_postorder()
82+
83+
print(self.value, end=" ")
84+
85+
def bfs_levelorder(self):
86+
"""
87+
The only reason we use `Queue` is because its FIFO principle, which
88+
eases the process of "traverse and then mark as discovered".
89+
"""
90+
queue = Queue()
91+
queue_first_put_first_out = queue.put
92+
queue_access_then_delete_first_out = queue.get
93+
94+
# Although you can't iterate them directly, you could know that
95+
# - the nodes are "sorted" (?because YOU inserted that way)
96+
# - the one in the foremost will be accessed first (lv0 -> lv1 ..)
97+
queue_first_put_first_out(self)
98+
99+
# All the nodes will be "checked" (all levels in case there's subtrees)
100+
while not queue.empty():
101+
102+
# remove/mark-as-discovered root node (lv0 -> lv1 -> lv2 ..)
103+
current_node = queue_access_then_delete_first_out()
104+
105+
print(current_node.value, end=" ")
106+
107+
# e.g. { a.L/R, b.L/R, .. h.L/R }
108+
if current_node.left:
109+
queue_first_put_first_out(current_node.left)
110+
111+
# e.g. { a.L/R, b.L/R, .. h.L/R }
112+
if current_node.right:
113+
queue_first_put_first_out(current_node.right)
114+
115+
116+
def main():
117+
# level zero
118+
root = BinaryTree("A")
119+
# level one
120+
root.insert_left("B")
121+
root.insert_right("C")
122+
# level two
123+
lv2_b_root = root.left
124+
lv2_b_root.insert_left("D")
125+
lv2_b_root.insert_right("E")
126+
lv2_c_root = root.right
127+
lv2_c_root.insert_left("F")
128+
lv2_c_root.insert_right("G")
129+
# level three
130+
lv3_d_root = lv2_b_root.left
131+
lv3_d_root.insert_left("H")
132+
133+
# A
134+
# B C
135+
# D E F G
136+
# H
137+
138+
# root.dfs_preorder() # A (B (D (H) E)) (C (F G))
139+
# root.dfs_inorder() # (H D B) E (A) (F C) G
140+
# root.dfs_postorder() # (H (D E) B) ((F G) C) A
141+
142+
root.bfs_levelorder()
143+
144+
145+
if "__main__" == __name__:
146+
main()

0 commit comments

Comments
 (0)