Skip to content

Commit dff30d0

Browse files
committed
final build tree
1 parent 5702627 commit dff30d0

File tree

1 file changed

+75
-141
lines changed

1 file changed

+75
-141
lines changed
Lines changed: 75 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -1,199 +1,133 @@
11
"""
2-
Build a binary tree from preorder + inorder or postorder + inorder traversals.
2+
Binary Tree Construction from Preorder/Inorder or Postorder/Inorder sequences.
33
4-
This module provides two main functions:
5-
- build_tree_from_preorder_and_inorder()
6-
- build_tree_from_postorder_and_inorder()
4+
This module allows building a binary tree when given:
75
8-
Each builds a binary tree represented by Node objects.
6+
- Preorder and inorder sequences
7+
- Postorder and inorder sequences
98
10-
References:
11-
- https://en.wikipedia.org/wiki/Binary_tree
12-
- https://en.wikipedia.org/wiki/Tree_traversal
9+
Doctest examples are included for verification.
1310
"""
1411

15-
from typing import Dict, List, Optional
12+
from __future__ import annotations # for forward references
13+
from typing import Optional
1614

1715

1816
class Node:
19-
"""
20-
A class representing a node in a binary tree.
21-
22-
Attributes:
23-
data (int): The value of the node.
24-
left (Optional[Node]): Pointer to the left child.
25-
right (Optional[Node]): Pointer to the right child.
26-
"""
17+
"""Class representing a node in a binary tree."""
2718

2819
def __init__(self, data: int) -> None:
29-
self.data = data
30-
self.left: Optional[Node] = None
31-
self.right: Optional[Node] = None
20+
self.data: int = data
21+
self.left: Node | None = None
22+
self.right: Node | None = None
23+
self.parent: Node | None = None
3224

3325

34-
def inorder_traversal(root: Optional[Node]) -> List[int]:
35-
"""
36-
Return the inorder traversal of a binary tree as a list.
37-
38-
>>> root = Node(3)
39-
>>> root.left = Node(2)
40-
>>> root.right = Node(4)
41-
>>> inorder_traversal(root)
42-
[2, 3, 4]
43-
"""
26+
def inorder_traversal(root: Node | None, out: list[int]) -> None:
27+
"""Perform normal inorder traversal and store values in 'out' list."""
4428
if root is None:
45-
return []
46-
return inorder_traversal(root.left) + [root.data] + inorder_traversal(root.right)
29+
return
30+
inorder_traversal(root.left, out)
31+
out.append(root.data)
32+
inorder_traversal(root.right, out)
4733

4834

4935
def _build_tree_from_preorder(
50-
preorder: List[int],
36+
preorder: list[int],
5137
pre_start: int,
5238
pre_end: int,
53-
inorder_seq: List[int],
39+
inorder: list[int],
5440
in_start: int,
5541
in_end: int,
56-
inorder_map: Dict[int, int],
57-
) -> Optional[Node]:
58-
"""Helper function for building a tree recursively from preorder + inorder."""
42+
in_map: dict[int, int],
43+
) -> Node | None:
44+
"""Internal recursive function to build tree from preorder & inorder."""
5945
if pre_start > pre_end or in_start > in_end:
6046
return None
6147

62-
root_value = preorder[pre_start]
63-
root = Node(root_value)
64-
in_root_index = inorder_map[root_value]
65-
left_subtree_size = in_root_index - in_start
48+
root = Node(preorder[pre_start])
49+
in_root_index = in_map[root.data]
50+
nums_left = in_root_index - in_start
6651

6752
root.left = _build_tree_from_preorder(
68-
preorder,
69-
pre_start + 1,
70-
pre_start + left_subtree_size,
71-
inorder_seq,
72-
in_start,
73-
in_root_index - 1,
74-
inorder_map,
53+
preorder, pre_start + 1, pre_start + nums_left,
54+
inorder, in_start, in_root_index - 1, in_map
7555
)
7656
root.right = _build_tree_from_preorder(
77-
preorder,
78-
pre_start + left_subtree_size + 1,
79-
pre_end,
80-
inorder_seq,
81-
in_root_index + 1,
82-
in_end,
83-
inorder_map,
57+
preorder, pre_start + nums_left + 1, pre_end,
58+
inorder, in_root_index + 1, in_end, in_map
8459
)
85-
return root
86-
8760

88-
def build_tree_from_preorder_and_inorder(
89-
inorder_seq: List[int], preorder_seq: List[int]
90-
) -> Optional[Node]:
91-
"""
92-
Build a binary tree from preorder and inorder traversals.
93-
94-
Args:
95-
inorder_seq: The inorder traversal sequence.
96-
preorder_seq: The preorder traversal sequence.
61+
return root
9762

98-
Returns:
99-
Root node of the reconstructed binary tree.
10063

101-
>>> inorder_seq = [1, 2, 3, 4, 5]
102-
>>> preorder_seq = [3, 2, 1, 4, 5]
103-
>>> root = build_tree_from_preorder_and_inorder(inorder_seq, preorder_seq)
104-
>>> inorder_traversal(root)
105-
[1, 2, 3, 4, 5]
106-
"""
107-
inorder_map = {value: i for i, value in enumerate(inorder_seq)}
108-
return _build_tree_from_preorder(
109-
preorder_seq,
110-
0,
111-
len(preorder_seq) - 1,
112-
inorder_seq,
113-
0,
114-
len(inorder_seq) - 1,
115-
inorder_map,
116-
)
64+
def build_tree_from_preorder(inorder: list[int], preorder: list[int]) -> Node | None:
65+
"""Build binary tree from preorder and inorder sequences."""
66+
in_map = {val: idx for idx, val in enumerate(inorder)}
67+
return _build_tree_from_preorder(preorder, 0, len(preorder) - 1, inorder, 0, len(inorder) - 1, in_map)
11768

11869

11970
def _build_tree_from_postorder(
120-
postorder: List[int],
71+
postorder: list[int],
12172
post_start: int,
12273
post_end: int,
123-
inorder_seq: List[int],
74+
inorder: list[int],
12475
in_start: int,
12576
in_end: int,
126-
inorder_map: Dict[int, int],
127-
) -> Optional[Node]:
128-
"""Helper function for building a tree recursively from postorder + inorder."""
77+
in_map: dict[int, int],
78+
) -> Node | None:
79+
"""
80+
Internal recursive function to build tree from postorder & inorder.
81+
82+
Example:
83+
>>> inorder_seq = [1, 2, 3]
84+
>>> postorder_seq = [1, 3, 2]
85+
>>> inmp = {v:i for i,v in enumerate(inorder_seq)}
86+
>>> root = _build_tree_from_postorder(postorder_seq, 0, 2, inorder_seq, 0, 2, inmp)
87+
>>> root.data
88+
2
89+
>>> root.left.data
90+
1
91+
>>> root.right.data
92+
3
93+
"""
12994
if post_start > post_end or in_start > in_end:
13095
return None
13196

132-
root_value = postorder[post_end]
133-
root = Node(root_value)
134-
in_root_index = inorder_map[root_value]
135-
left_subtree_size = in_root_index - in_start
97+
root = Node(postorder[post_end])
98+
in_root_index = in_map[root.data]
99+
nums_left = in_root_index - in_start
136100

137101
root.left = _build_tree_from_postorder(
138-
postorder,
139-
post_start,
140-
post_start + left_subtree_size - 1,
141-
inorder_seq,
142-
in_start,
143-
in_root_index - 1,
144-
inorder_map,
102+
postorder, post_start, post_start + nums_left - 1,
103+
inorder, in_start, in_root_index - 1, in_map
145104
)
146105
root.right = _build_tree_from_postorder(
147-
postorder,
148-
post_start + left_subtree_size,
149-
post_end - 1,
150-
inorder_seq,
151-
in_root_index + 1,
152-
in_end,
153-
inorder_map,
106+
postorder, post_start + nums_left, post_end - 1,
107+
inorder, in_root_index + 1, in_end, in_map
154108
)
155-
return root
156-
157109

158-
def build_tree_from_postorder_and_inorder(
159-
inorder_seq: List[int], postorder_seq: List[int]
160-
) -> Optional[Node]:
161-
"""
162-
Build a binary tree from postorder and inorder traversals.
163-
164-
Args:
165-
inorder_seq: The inorder traversal sequence.
166-
postorder_seq: The postorder traversal sequence.
110+
return root
167111

168-
Returns:
169-
Root node of the reconstructed binary tree.
170112

171-
>>> inorder_seq = [1, 2, 3, 4, 5]
172-
>>> postorder_seq = [1, 2, 5, 4, 3]
173-
>>> root = build_tree_from_postorder_and_inorder(inorder_seq, postorder_seq)
174-
>>> inorder_traversal(root)
175-
[1, 2, 3, 4, 5]
176-
"""
177-
inorder_map = {value: i for i, value in enumerate(inorder_seq)}
178-
return _build_tree_from_postorder(
179-
postorder_seq,
180-
0,
181-
len(postorder_seq) - 1,
182-
inorder_seq,
183-
0,
184-
len(inorder_seq) - 1,
185-
inorder_map,
186-
)
113+
def build_tree_from_postorder(inorder: list[int], postorder: list[int]) -> Node | None:
114+
"""Build binary tree from postorder and inorder sequences."""
115+
in_map = {val: idx for idx, val in enumerate(inorder)}
116+
return _build_tree_from_postorder(postorder, 0, len(postorder) - 1, inorder, 0, len(inorder) - 1, in_map)
187117

188118

119+
# Optional example usage
189120
if __name__ == "__main__":
190-
# Example usage for manual verification (not part of algorithmic test)
191121
inorder_seq = [1, 2, 3, 4, 5]
192122
preorder_seq = [3, 2, 1, 4, 5]
193123
postorder_seq = [1, 2, 5, 4, 3]
194124

195-
root_pre = build_tree_from_preorder_and_inorder(inorder_seq, preorder_seq)
196-
print("Inorder (from Preorder+Inorder):", inorder_traversal(root_pre))
125+
tree_pre = build_tree_from_preorder(inorder_seq, preorder_seq)
126+
tree_post = build_tree_from_postorder(inorder_seq, postorder_seq)
197127

198-
root_post = build_tree_from_postorder_and_inorder(inorder_seq, postorder_seq)
199-
print("Inorder (from Postorder+Inorder):", inorder_traversal(root_post))
128+
out: list[int] = []
129+
inorder_traversal(tree_pre, out)
130+
print("Inorder from Preorder Tree:", out)
131+
out.clear()
132+
inorder_traversal(tree_post, out)
133+
print("Inorder from Postorder Tree:", out)

0 commit comments

Comments
 (0)