Skip to content

Commit 3557e10

Browse files
authored
Update basic_binary_tree.py
Comments added with mechanism
1 parent 788d95b commit 3557e10

File tree

1 file changed

+64
-23
lines changed

1 file changed

+64
-23
lines changed
Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,70 @@
1-
from __future__ import annotations
1+
from __future__ import annotations # Allows using the class itself as a type hint within the class
22

3-
from collections.abc import Iterator
4-
from dataclasses import dataclass
3+
from collections.abc import Iterator # For type hinting iteration
4+
from dataclasses import dataclass # For concise class definitions
55

66

7+
# -----------------------------
8+
# Node class: represents one node in the binary tree
9+
# -----------------------------
710
@dataclass
811
class Node:
9-
data: int
10-
left: Node | None = None
11-
right: Node | None = None
12-
12+
data: int # Value stored in the node
13+
left: Node | None = None # Left child node
14+
right: Node | None = None # Right child node
15+
16+
# -----------------------------
17+
# In-order traversal generator
18+
# Allows iterating over Node like: `for x in node: ...`
19+
# -----------------------------
1320
def __iter__(self) -> Iterator[int]:
1421
if self.left:
15-
yield from self.left
16-
yield self.data
22+
yield from self.left # Yield all values from the left subtree
23+
yield self.data # Yield the current node's data
1724
if self.right:
18-
yield from self.right
25+
yield from self.right # Yield all values from the right subtree
1926

27+
# -----------------------------
28+
# Returns number of nodes in the subtree rooted at this node
29+
# -----------------------------
2030
def __len__(self) -> int:
21-
return sum(1 for _ in self)
31+
return sum(1 for _ in self) # Count all nodes using iteration
2232

33+
# -----------------------------
34+
# Check if the subtree rooted at this node is a full binary tree
35+
# A full binary tree: every node has 0 or 2 children
36+
# -----------------------------
2337
def is_full(self) -> bool:
2438
if not self or (not self.left and not self.right):
25-
return True
39+
return True # Leaf node is full
2640
if self.left and self.right:
41+
# Node has two children → recursively check both subtrees
2742
return self.left.is_full() and self.right.is_full()
28-
return False
43+
return False # Node has only one child → not full
2944

3045

46+
# -----------------------------
47+
# BinaryTree class: represents the whole binary tree
48+
# -----------------------------
3149
@dataclass
3250
class BinaryTree:
33-
root: Node
51+
root: Node # Root node of the tree
3452

53+
# -----------------------------
54+
# Iterate over tree using in-order traversal
55+
# -----------------------------
3556
def __iter__(self) -> Iterator[int]:
3657
return iter(self.root)
3758

59+
# -----------------------------
60+
# Return total number of nodes in the tree
61+
# -----------------------------
3862
def __len__(self) -> int:
3963
return len(self.root)
4064

65+
# -----------------------------
66+
# Factory method: small tree (3 nodes)
67+
# -----------------------------
4168
@classmethod
4269
def small_tree(cls) -> BinaryTree:
4370
"""
@@ -48,22 +75,25 @@ def small_tree(cls) -> BinaryTree:
4875
>>> list(binary_tree)
4976
[1, 2, 3]
5077
"""
51-
binary_tree = BinaryTree(Node(2))
52-
binary_tree.root.left = Node(1)
53-
binary_tree.root.right = Node(3)
78+
binary_tree = BinaryTree(Node(2)) # Root node = 2
79+
binary_tree.root.left = Node(1) # Left child
80+
binary_tree.root.right = Node(3) # Right child
5481
return binary_tree
5582

83+
# -----------------------------
84+
# Factory method: medium tree (7 nodes)
85+
# -----------------------------
5686
@classmethod
5787
def medium_tree(cls) -> BinaryTree:
5888
"""
59-
Return a medium binary tree with 3 nodes.
89+
Return a medium binary tree with 7 nodes.
6090
>>> binary_tree = BinaryTree.medium_tree()
6191
>>> len(binary_tree)
6292
7
6393
>>> list(binary_tree)
6494
[1, 2, 3, 4, 5, 6, 7]
6595
"""
66-
binary_tree = BinaryTree(Node(4))
96+
binary_tree = BinaryTree(Node(4)) # Root node = 4
6797
binary_tree.root.left = two = Node(2)
6898
two.left = Node(1)
6999
two.right = Node(3)
@@ -72,10 +102,12 @@ def medium_tree(cls) -> BinaryTree:
72102
six.right = Node(7)
73103
return binary_tree
74104

105+
# -----------------------------
106+
# Public method: get depth of tree
107+
# -----------------------------
75108
def depth(self) -> int:
76109
"""
77110
Returns the depth of the tree
78-
79111
>>> BinaryTree(Node(1)).depth()
80112
1
81113
>>> BinaryTree.small_tree().depth()
@@ -85,15 +117,21 @@ def depth(self) -> int:
85117
"""
86118
return self._depth(self.root)
87119

120+
# -----------------------------
121+
# Helper recursive method to compute depth
122+
# Depth = 1 + max(depth of left, depth of right)
123+
# -----------------------------
88124
def _depth(self, node: Node | None) -> int:
89125
if not node:
90-
return 0
126+
return 0 # Empty node contributes 0 to depth
91127
return 1 + max(self._depth(node.left), self._depth(node.right))
92128

129+
# -----------------------------
130+
# Check if the tree is full
131+
# -----------------------------
93132
def is_full(self) -> bool:
94133
"""
95134
Returns True if the tree is full
96-
97135
>>> BinaryTree(Node(1)).is_full()
98136
True
99137
>>> BinaryTree.small_tree().is_full()
@@ -104,7 +142,10 @@ def is_full(self) -> bool:
104142
return self.root.is_full()
105143

106144

145+
# -----------------------------
146+
# Run doctests if executed as main
147+
# -----------------------------
107148
if __name__ == "__main__":
108149
import doctest
109150

110-
doctest.testmod()
151+
doctest.testmod() # Automatically tests all docstring examples

0 commit comments

Comments
 (0)