Skip to content

Commit 7cc2602

Browse files
authored
Use dataclass .__eq__(), .__iter__(), and .__repr__()
1 parent 44ec94d commit 7cc2602

File tree

1 file changed

+85
-100
lines changed

1 file changed

+85
-100
lines changed

Diff for: data_structures/binary_tree/serialize_deserialize_binary_tree.py

+85-100
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,86 @@
11
from __future__ import annotations
22

3+
from collections.abc import Iterator
4+
from dataclasses import dataclass
35

6+
7+
@dataclass
48
class TreeNode:
59
"""
610
A binary tree node has a value, left child, and right child.
711
812
Props:
9-
val(int): The value of the node.
13+
value: The value of the node.
1014
left: The left child of the node.
1115
right: The right child of the node.
1216
"""
1317

14-
def __init__(
15-
self,
16-
val: int = 0,
17-
left: TreeNode | None = None,
18-
right: TreeNode | None = None,
19-
) -> None:
20-
if not isinstance(val, int):
21-
raise TypeError("Value must be an integer.")
22-
self.val = val
23-
self.left = left
24-
self.right = right
25-
26-
27-
# Helper functions
28-
def are_trees_identical(root1: TreeNode | None, root2: TreeNode | None) -> bool:
29-
"""
30-
Check if two binary trees are identical.
31-
32-
Args:
33-
root1 (TreeNode): Tree 1
34-
root2 (TreeNode): Tree 2
35-
36-
Returns:
37-
bool: True if the trees are identical, False otherwise.
38-
39-
>>> root1 = TreeNode(1)
40-
>>> root1.left = TreeNode(2)
41-
>>> root1.right = TreeNode(3)
42-
>>> root2 = TreeNode(1)
43-
>>> root2.left = TreeNode(2)
44-
>>> root2.right = TreeNode(3)
45-
>>> are_trees_identical(root1, root2)
46-
True
47-
>>> root1 = TreeNode(1)
48-
>>> root1.left = TreeNode(2)
49-
>>> root1.right = TreeNode(3)
50-
>>> root2 = TreeNode(1)
51-
>>> root2.left = TreeNode(2)
52-
>>> root2.right = TreeNode(4)
53-
>>> are_trees_identical(root1, root2)
54-
False
55-
"""
56-
57-
if not root1 and not root2:
58-
return True
59-
if not root1 or not root2:
60-
return False
61-
62-
return (
63-
root1.val == root2.val
64-
and are_trees_identical(root1.left, root2.left)
65-
and are_trees_identical(root1.right, root2.right)
66-
)
18+
value: int = 0
19+
left: TreeNode | None = None
20+
right: TreeNode | None = None
6721

22+
def __post_init__(self):
23+
if not isinstance(self.value, int):
24+
raise TypeError("Value must be an integer.")
6825

69-
# Main functions
70-
def serialize(root: TreeNode | None) -> str:
71-
"""
72-
Serialize a binary tree to a string using preorder traversal.
73-
74-
Args:
75-
root(TreeNode): The root of the binary tree.
76-
77-
Returns:
78-
A string representation of the binary tree.
79-
80-
>>> root = TreeNode(1)
81-
>>> root.left = TreeNode(2)
82-
>>> root.right = TreeNode(3)
83-
>>> root.right.left = TreeNode(4)
84-
>>> root.right.right = TreeNode(5)
85-
>>> serialize(root)
86-
'1,2,null,null,3,4,null,null,5,null,null'
87-
>>> root = TreeNode(1)
88-
>>> serialize(root)
89-
'1,null,null'
90-
"""
91-
92-
# Use "null" to represent empty nodes in the serialization
93-
if not root:
94-
return "null"
95-
96-
return str(root.val) + "," + serialize(root.left) + "," + serialize(root.right)
26+
def __iter__(self) -> Iterator[TreeNode]:
27+
"""
28+
Iterate through the tree in preorder.
29+
30+
Returns:
31+
An iterator of the tree nodes.
32+
33+
>>> list(TreeNode(1))
34+
[1,null,null]
35+
>>> tuple(TreeNode(1, TreeNode(2), TreeNode(3)))
36+
(1,2,null,null,3,null,null, 2,null,null, 3,null,null)
37+
"""
38+
yield self
39+
yield from self.left or ()
40+
yield from self.right or ()
41+
42+
def __len__(self) -> int:
43+
"""
44+
Count the number of nodes in the tree.
45+
46+
Returns:
47+
The number of nodes in the tree.
48+
49+
>>> len(TreeNode(1))
50+
1
51+
>>> len(TreeNode(1, TreeNode(2), TreeNode(3)))
52+
3
53+
"""
54+
return sum(1 for _ in self)
55+
56+
def __repr__(self) -> str:
57+
"""
58+
Represent the tree as a string.
59+
60+
Returns:
61+
A string representation of the tree.
62+
63+
>>> repr(TreeNode(1))
64+
'1,null,null'
65+
>>> repr(TreeNode(1, TreeNode(2), TreeNode(3)))
66+
'1,2,null,null,3,null,null'
67+
>>> repr(TreeNode(1, TreeNode(2), TreeNode(3, TreeNode(4), TreeNode(5))))
68+
'1,2,null,null,3,4,null,null,5,null,null'
69+
"""
70+
return f"{self.value},{self.left!r},{self.right!r}".replace("None", "null")
71+
72+
@classmethod
73+
def five_tree(cls) -> TreeNode:
74+
"""
75+
>>> repr(TreeNode.five_tree())
76+
'1,2,null,null,3,4,null,null,5,null,null'
77+
"""
78+
root = TreeNode(1)
79+
root.left = TreeNode(2)
80+
root.right = TreeNode(3)
81+
root.right.left = TreeNode(4)
82+
root.right.right = TreeNode(5)
83+
return root
9784

9885

9986
def deserialize(data: str) -> TreeNode | None:
@@ -106,44 +93,42 @@ def deserialize(data: str) -> TreeNode | None:
10693
Returns:
10794
The root of the binary tree.
10895
109-
>>> root = TreeNode(1)
110-
>>> root.left = TreeNode(2)
111-
>>> root.right = TreeNode(3)
112-
>>> root.right.left = TreeNode(4)
113-
>>> root.right.right = TreeNode(5)
114-
>>> serialzed_data = serialize(root)
96+
>>> root = TreeNode.five_tree()
97+
>>> serialzed_data = repr(root)
11598
>>> deserialized = deserialize(serialzed_data)
116-
>>> are_trees_identical(root, deserialized)
99+
>>> root == deserialized
117100
True
118-
>>> root = TreeNode(1)
119-
>>> serialzed_data = serialize(root)
120-
>>> dummy_data = "1,2,null,null,3,4,null,null,5,null,null"
121-
>>> deserialized = deserialize(dummy_data)
122-
>>> are_trees_identical(root, deserialized)
101+
>>> root is deserialized # two separate trees
102+
False
103+
>>> root.right.right.value = 6
104+
>>> root == deserialized
123105
False
106+
>>> serialzed_data = repr(root)
107+
>>> deserialized = deserialize(serialzed_data)
108+
>>> root == deserialized
109+
True
124110
>>> deserialize("")
125111
Traceback (most recent call last):
126112
...
127113
ValueError: Data cannot be empty.
128114
"""
129115

130-
if data == "":
116+
if not data:
131117
raise ValueError("Data cannot be empty.")
132118

133-
# Split the serialized string by comma to get node values
119+
# Split the serialized string by a comma to get node values
134120
nodes = data.split(",")
135121

136122
def build_tree() -> TreeNode | None:
137123
# Get the next value from the list
138-
val = nodes.pop(0)
124+
value = nodes.pop(0)
139125

140-
if val == "null":
126+
if value == "null":
141127
return None
142128

143-
node = TreeNode(int(val))
129+
node = TreeNode(int(value))
144130
node.left = build_tree() # Recursively build left subtree
145131
node.right = build_tree() # Recursively build right subtree
146-
147132
return node
148133

149134
return build_tree()

0 commit comments

Comments
 (0)