Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Construct Binary Search Tree from Preorder Traversal in Python
A Binary Search Tree (BST) can be constructed from its preorder traversal using a stack-based approach. In preorder traversal, we visit the root first, then the left subtree, followed by the right subtree.
Algorithm Steps
The algorithm uses a stack to keep track of potential parent nodes ?
- Create root from the first element of preorder traversal
- Initialize a stack and push the root node
- For each remaining element in preorder:
- If current value is less than stack top, it goes to the left
- If current value is greater, find the correct parent by popping from stack
- Return the constructed root
Implementation
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def bst_from_preorder(preorder):
if not preorder:
return None
root = TreeNode(preorder[0])
stack = [root]
for i in range(1, len(preorder)):
node = TreeNode(preorder[i])
if node.val < stack[-1].val:
# Current node goes to left of stack top
stack[-1].left = node
stack.append(node)
else:
# Find the correct parent for right child
while stack and stack[-1].val < node.val:
last = stack.pop()
last.right = node
stack.append(node)
return root
# Helper function to print inorder traversal for verification
def inorder_traversal(root):
if not root:
return []
return inorder_traversal(root.left) + [root.val] + inorder_traversal(root.right)
# Test the implementation
preorder = [8, 5, 1, 7, 10, 12]
root = bst_from_preorder(preorder)
inorder_result = inorder_traversal(root)
print("Preorder input:", preorder)
print("Inorder output:", inorder_result)
print("Valid BST:", inorder_result == sorted(preorder))
Preorder input: [8, 5, 1, 7, 10, 12] Inorder output: [1, 5, 7, 8, 10, 12] Valid BST: True
How It Works
The stack maintains nodes that could potentially have right children. When we encounter a value smaller than the stack top, it becomes a left child. When we encounter a larger value, we pop from the stack until we find the correct parent for the right child ?
Step-by-Step Example
def bst_from_preorder_detailed(preorder):
if not preorder:
return None
root = TreeNode(preorder[0])
stack = [root]
print(f"Created root: {root.val}, Stack: [{root.val}]")
for i in range(1, len(preorder)):
node = TreeNode(preorder[i])
print(f"\nProcessing: {node.val}")
if node.val < stack[-1].val:
stack[-1].left = node
stack.append(node)
stack_vals = [n.val for n in stack]
print(f" Added as left child of {stack[-2].val}")
print(f" Stack: {stack_vals}")
else:
while stack and stack[-1].val < node.val:
last = stack.pop()
print(f" Popped: {last.val}")
last.right = node
stack.append(node)
stack_vals = [n.val for n in stack]
print(f" Added as right child of {last.val}")
print(f" Stack: {stack_vals}")
return root
# Demonstrate with example
preorder = [8, 5, 1, 7, 10, 12]
bst_from_preorder_detailed(preorder)
Created root: 8, Stack: [8] Processing: 5 Added as left child of 8 Stack: [8, 5] Processing: 1 Added as left child of 5 Stack: [8, 5, 1] Processing: 7 Popped: 1 Added as right child of 1 Stack: [8, 5, 7] Processing: 10 Popped: 7 Popped: 5 Added as right child of 5 Stack: [8, 10] Processing: 12 Added as right child of 10 Stack: [8, 10, 12]
Time and Space Complexity
| Complexity | Value | Explanation |
|---|---|---|
| Time | O(n) | Each element is pushed and popped at most once |
| Space | O(n) | Stack can hold up to n nodes in worst case |
Conclusion
The stack-based approach efficiently constructs a BST from preorder traversal in O(n) time. The key insight is using the stack to track potential parents and determining left/right placement based on value comparisons with the stack top.
