Back to Data Structures & Algorithms
2026-04-088 min read

Tree based DSA (I) (Data Structures & Algorithms)

Learn Tree based DSA (I) (Data Structures & Algorithms) step by step with clear examples and exercises.

Why This Matters

Welcome to our full guide on Tree based Data Structures and Algorithms using Python! In this tutorial, we will delve into the world of trees, an essential data structure used in computer science for organizing data hierarchically. Trees are crucial for managing complex data efficiently and are used extensively in various real-world applications such as file systems, compiler design, parsing, and graph traversal. Understanding trees can also be beneficial during job interviews or competitive programming contests, where tree-related problems are common.

Importance of Trees

  1. Efficient data management: Trees allow for efficient storage and retrieval of large amounts of data with hierarchical relationships.
  2. Reduced search complexity: Trees can significantly reduce the average time complexity of search operations, making them ideal for applications requiring frequent lookups.
  3. Balanced structures: Self-balancing trees like AVL and Red-Black trees ensure that the height of the tree remains logarithmic, providing optimal performance even in dynamic scenarios.
  4. Flexibility: Trees can be adapted to various use cases, such as binary search trees (BSTs), AVL trees, Binary Heaps, and Tries, each with its unique advantages and applications.
  5. Optimized traversal: Trees allow for efficient traversal patterns like Depth-First Search (DFS) and Breadth-First Search (BFS), making them useful in graph algorithms and network analysis.

Prerequisites

Before diving into the core concept of trees, it is essential to have a solid understanding of the following topics:

  1. Basic Python syntax and control structures (if-else, for loops, while loops)
  2. Data Structures like Lists and Dictionaries
  3. Recursion concepts
  4. Understanding Big O notation
  5. Familiarity with graph data structures and algorithms
  6. Knowledge of basic sorting and searching algorithms
  7. Understanding the concept of stacks and queues
  8. Familiarity with Python's built-in functions like len(), min(), max(), and sorted()
  9. Basic understanding of Python classes and objects

Core Concept

A tree is a hierarchical data structure consisting of nodes connected by edges. The nodes in the tree can have zero or more children, except for the root node, which has at least one child. In Python, we can represent trees using nested lists, tuples, or classes.

Types of Trees

  1. Binary Tree: A tree where each node has at most two children (left and right).
  2. N-ary Tree: A tree where each node can have more than two children.
  3. AVL Tree: A self-balancing binary search tree, which maintains the height difference between its subtrees within a specific limit.
  4. Binary Search Tree (BST): A binary tree in which the left subtree of any node contains only nodes with keys less than the node itself, and the right subtree contains only nodes with keys greater than the node itself.
  5. Trie: A prefix tree used to efficiently store a set of strings, where each node represents a character and its children store strings starting with that character.
  6. Heap: A complete binary tree in which every node's key is greater (max-heap) or less (min-heap) than its children's keys.

Tree Traversals

There are four common ways to traverse a tree:

  1. In-order traversal: Visit the left subtree, then the current node, and finally the right subtree (LNR). This order is useful for visiting nodes in sorted order or performing operations on the nodes' data.
  2. Pre-order traversal: Visit the current node, then the left subtree, and finally the right subtree (NLR). This order is useful when constructing the tree from its elements or performing depth-first search (DFS) operations.
  3. Post-order traversal: Visit the left subtree, then the right subtree, and finally the current node (LRL). This order is useful for deleting nodes without affecting their descendants or performing certain graph traversal algorithms like DFS.
  4. Level Order Traversal: Traverse the tree level by level from top to bottom. This order is useful for breadth-first search (BFS) operations and calculating properties like the height of the tree.
  5. Depth First Search (DFS): A recursive algorithm that explores as far as possible along each branch before backtracking. It can be implemented using either DFS traversal orders or BFS with a depth limit.
  6. Breadth First Search (BFS): An iterative algorithm that explores all nodes at the current level before moving to the next level. It is useful for finding the shortest path between two nodes in an unweighted graph.

Worked Example

Let's create a simple binary search tree and perform common operations like insertion, deletion, and traversals using Python classes.

class Node:
def __init__(self, key):
self.left = None
self.right = None
self.val = key

def insert(self, root, key):
if not root:
return Node(key)
else:
if root.val < key:
root.right = root.right.insert(root.right, key)
else:
root.left = root.left.insert(root.left, key)
return root

def inorder_traversal(self, root):
if root:
self.inorder_traversal(root.left)
print(root.val),
self.inorder_traversal(root.right)

class AVLTree(Node):
def __init__(self, key=None):
super().__init__(key)
self.height = 0

def get_balance_factor(self):
return self.left.height - self.right.height if self.right else float('inf')

def update_height(self):
self.height = max(self.left.height, self.right.height) + 1

def rotate_right(self):
new_root = self.left
self.left = new_root.right
new_root.right = self
new_root.update_height()
self.update_height()

def rotate_left(self):
new_root = self.right
self.right = new_root.left
new_root.left = self
new_root.update_height()
self.update_height()

def insert(self, key):
if not self:
return AVLTree(key)
root = super().insert(self, key)
balance = root.get_balance_factor()
if balance > 1 and root.left.get_balance_factor() >= 0:
root.rotate_right()
elif balance > 1 and root.left.get_balance_factor() < 0:
root.left.rotate_left()
root.rotate_right()
elif balance < -1 and root.right.get_balance_factor() <= 0:
root.rotate_left()
elif balance < -1 and root.right.get_balance_factor() > 0:
root.right.rotate_right()
root.rotate_left()
return root

Now let's create an AVL tree and perform some operations:

r = AVLTree(50)
r = r.insert(30)
r = r.insert(20)
r = r.insert(40)
r = r.insert(70)
r = r.insert(60)
r = r.insert(80)

r.inorder_traversal() # Output: 20 30 40 50 60 70 80

Common Mistakes

  1. Forgetting to check if the node is None before performing operations (e.g., insert, delete).
  2. Incorrectly implementing tree traversals, especially when dealing with complex cases like nested nodes or empty trees.
  3. Neglecting to maintain the balance in AVL trees during insertion and deletion.
  4. Implementing incorrect comparison functions for BSTs, leading to an unbalanced tree structure.
  5. Misunderstanding the difference between a binary search tree and a binary heap.
  6. Failing to handle edge cases like empty or singleton trees in various operations.
  7. Not properly handling cyclic structures in graphs during graph traversals.
  8. Implementing inefficient algorithms for common operations like finding the minimum, maximum, or successor/predecessor nodes.
  9. Overcomplicating tree implementations by not leveraging Python's built-in data structures and functions.
  10. Failing to optimize traversal patterns for specific applications, such as using BFS instead of DFS when necessary.

Practice Questions

  1. Implement depth-first search (DFS) on a given graph represented as an adjacency list.
  2. Write a Python function to find the height of a binary tree.
  3. Implement a Trie data structure in Python.
  4. Given a BST, write a function to check if it is a valid BST.
  5. Write a Python function to find the minimum depth of a binary tree.
  6. Implement breadth-first search (BFS) on a given graph represented as an adjacency list.
  7. Given a binary tree, write a function to find its diameter (longest path between any two nodes).
  8. Write a Python function to check if two trees are identical.
  9. Implement the left and right rotations for AVL trees using Python classes.
  10. Write a Python function to delete a node from an AVL tree while maintaining its balance.
  11. Given a binary search tree, write a function to find the kth smallest element.
  12. Implement a function to convert a binary tree into a doubly linked list in-order traversal format.
  13. Write a Python function to find the lowest common ancestor (LCA) of two nodes in a binary tree.
  14. Given a binary tree, write a function to check if it is a complete binary tree.
  15. Implement a function to serialize and deserialize a binary tree using Depth-First Search (DFS).

FAQ

What is the time complexity of inserting an element in a BST?

Ans: The average time complexity for insertion in a BST is O(log n), where n is the number of elements in the tree.

How can I check if a given tree is a binary search tree (BST)?

Ans: To check if a given tree is a valid BST, you can perform an in-order traversal and ensure that the current node's value is greater than its left subtree's values and less than its right subtree's values.

What are the advantages of using AVL trees over regular BSTs?

Ans: AVL trees are self-balancing binary search trees that maintain a logarithmic height in the worst case, ensuring faster search operations. This is achieved by performing rotations to balance the tree during insertion and deletion.

What is the time complexity of searching for an element in a BST?

Ans: The average time complexity for searching an element in a BST is O(log n), where n is the number of elements in the tree.

How can I find the height of a binary tree using Python?

Ans: To find the height of a binary tree, you can recursively calculate the maximum depth of its left and right subtrees plus one for the current node's level.

Tree based DSA (I) (Data Structures & Algorithms) | Data Structures & Algorithms | XQA Learn