Trees are a fundamental data structure used in computer science to represent hierarchical relationships between elements. They consist of nodes connected by edges and have a root node from which all other nodes descend. Understanding trees is crucial for various applications such as file systems, organization charts, and decision-making processes.
In this tutorial, we'll explore the basics of tree structures, delve into binary trees, and implement a Binary Search Tree (BST). We'll cover different types of traversals—such as inorder, preorder, postorder, and level-order—and learn how to perform essential operations like insert, search, and delete in a BST.
A tree is a non-linear data structure that represents hierarchical relationships. It consists of nodes where each node can have zero or more child nodes. The topmost node is called the root, and any node without children is called a leaf.
Think of a family tree as an example of a tree data structure. Each person (node) has parents and possibly children, forming a hierarchical relationship.
A binary tree is a specific type of tree where each node can have at most two child nodes: a left child and a right child. This property makes binary trees particularly useful for efficient searching and sorting operations.
Binary trees can be likened to a decision-making process, such as a game where you make choices that lead to different outcomes.
A Binary Search Tree is a type of binary tree where each node has a key, and for every node:
This property allows BSTs to perform efficient search, insert, and delete operations.
Let's start by implementing a basic binary tree in Python.
1class TreeNode:2def __init__(self, key):3self.left = None4self.right = None5self.val = key67# Function to insert a new node with the given key8def insert(root, key):9if root is None:10return TreeNode(key)11else:12if root.val < key:13root.right = insert(root.right, key)14else:15root.left = insert(root.left, key)16return root1718# Function to do inorder tree traversal19def inorder_traversal(root):20if root:21inorder_traversal(root.left)22print(root.val, end=" ")23inorder_traversal(root.right)2425# Driver code26r = TreeNode(50)27r = insert(r, 30)28r = insert(r, 20)29r = insert(r, 40)30r = insert(r, 70)31r = insert(r, 60)32r = insert(r, 80)3334print("Inorder traversal of the binary tree is:")35inorder_traversal(r)
Inorder traversal of the binary tree is: 20 30 40 50 60 70 80
Traversing a tree means visiting all its nodes in a specific order. There are several ways to traverse a binary tree:
Let's implement these traversals in Python.
1class TreeNode:2def __init__(self, key):3self.left = None4self.right = None5self.val = key67def insert(root, key):8if root is None:9return TreeNode(key)10else:11if root.val < key:12root.right = insert(root.right, key)13else:14root.left = insert(root.left, key)15return root1617# Inorder Traversal18def inorder_traversal(root):19if root:20inorder_traversal(root.left)21print(root.val, end=" ")22inorder_traversal(root.right)2324# Preorder Traversal25def preorder_traversal(root):26if root:27print(root.val, end=" ")28preorder_traversal(root.left)29preorder_traversal(root.right)3031# Postorder Traversal32def postorder_traversal(root):33if root:34postorder_traversal(root.left)35postorder_traversal(root.right)36print(root.val, end=" ")3738# Level-order Traversal (BFS)39from collections import deque4041def level_order_traversal(root):42if not root:43return44queue = deque([root])45while queue:46node = queue.popleft()47print(node.val, end=" ")48if node.left:49queue.append(node.left)50if node.right:51queue.append(node.right)5253# Driver code54r = TreeNode(50)55r = insert(r, 30)56r = insert(r, 20)57r = insert(r, 40)58r = insert(r, 70)59r = insert(r, 60)60r = insert(r, 80)6162print("Inorder traversal of the binary tree is:")63inorder_traversal(r)64print("65Preorder traversal of the binary tree is:")66preorder_traversal(r)67print("68Postorder traversal of the binary tree is:")69postorder_traversal(r)70print("71Level-order traversal of the binary tree is:")72level_order_traversal(r)
Inorder traversal of the binary tree is: 20 30 40 50 60 70 80 Preorder traversal of the binary tree is: 50 30 20 40 70 60 80 Postorder traversal of the binary tree is: 20 40 30 60 80 70 50 Level-order traversal of the binary tree is: 50 30 70 20 40 60 80
Now, let's implement a BST and perform basic operations like insert, search, and delete.
1class TreeNode:2def __init__(self, key):3self.left = None4self.right = None5self.val = key67def insert(root, key):8if root is None:9return TreeNode(key)10else:11if root.val < key:12root.right = insert(root.right, key)13else:14root.left = insert(root.left, key)15return root1617def search(root, key):18if root is None or root.val == key:19return root20if root.val < key:21return search(root.right, key)22return search(root.left, key)2324def delete_node(root, key):25if root is None:26return root27if key < root.val:28root.left = delete_node(root.left, key)29elif key > root.val:30root.right = delete_node(root.right, key)31else:32if root.left is None:33temp = root.right34root = None35return temp36elif root.right is None:37temp = root.left38root = None39return temp40temp = minValueNode(root.right)41root.val = temp.val42root.right = delete_node(root.right, temp.val)43return root4445def minValueNode(node):46current = node47while current.left is not None:48current = current.left49return current5051# Driver code52r = TreeNode(50)53r = insert(r, 30)54r = insert(r, 20)55r = insert(r, 40)56r = insert(r, 70)57r = insert(r, 60)58r = insert(r, 80)5960print("Inorder traversal of the BST is:")61inorder_traversal(r)6263key = 2064if search(r, key):65print(f"66{key} found in the BST.")67else:68print(f"69{key} not found in the BST.")7071r = delete_node(r, 20)72print("73Inorder traversal after deleting 20:")74inorder_traversal(r)7576r = delete_node(r, 30)77print("78Inorder traversal after deleting 30:")79inorder_traversal(r)8081r = delete_node(r, 50)82print("83Inorder traversal after deleting 50:")84inorder_traversal(r)
Inorder traversal of the BST is: 20 30 40 50 60 70 80 20 found in the BST. Inorder traversal after deleting 20: 30 40 50 60 70 80 Inorder traversal after deleting 30: 40 50 60 70 80 Inorder traversal after deleting 50: 40 60 70 80
None values: Always check if a node is None before accessing its properties to avoid errors.Let's create a complete program that allows users to insert, search, and delete elements in a BST.
1class TreeNode:2def __init__(self, key):3self.left = None4self.right = None5self.val = key67def insert(root, key):8if root is None:9return TreeNode(key)10else:11if root.val < key:12root.right = insert(root.right, key)13else:14root.left = insert(root.left, key)15return root1617def search(root, key):18if root is None or root.val == key:19return root20if root.val < key:21return search(root.right, key)22return search(root.left, key)2324def delete_node(root, key):25if root is None:26return root27if key < root.val:28root.left = delete_node(root.left, key)29elif key > root.val:30root.right = delete_node(root.right, key)31else:32if root.left is None:33temp = root.right34root = None35return temp36elif root.right is None:37temp = root.left38root = None39return temp40temp = minValueNode(root.right)41root.val = temp.val42root.right = delete_node(root.right, temp.val)43return root4445def minValueNode(node):46current = node47while current.left is not None:48current = current.left49return current5051def inorder_traversal(root):52if root:53inorder_traversal(root.left)54print(root.val, end=" ")55inorder_traversal(root.right)5657# Driver code58r = TreeNode(50)59r = insert(r, 30)60r = insert(r, 20)61r = insert(r, 40)62r = insert(r, 70)63r = insert(r, 60)64r = insert(r, 80)6566print("Inorder traversal of the BST is:")67inorder_traversal(r)6869key = 2070if search(r, key):71print(f"72{key} found in the BST.")73else:74print(f"75{key} not found in the BST.")7677r = delete_node(r, 20)78print("79Inorder traversal after deleting 20:")80inorder_traversal(r)8182r = delete_node(r, 30)83print("84Inorder traversal after deleting 30:")85inorder_traversal(r)8687r = delete_node(r, 50)88print("89Inorder traversal after deleting 50:")90inorder_traversal(r)
| Concept | Description |
|---|---|
| Tree | A hierarchical data structure with nodes connected by edges. |
| Binary Tree | Each node has at most two child nodes: left and right. |
| Binary Search Tree (BST) | A binary tree where the left subtree contains only smaller keys, and the right subtree contains only larger keys. |
| Inorder Traversal | Visits nodes in this order: Left subtree, Root node, Right subtree. |
| Preorder Traversal | Visits nodes in this order: Root node, Left subtree, Right subtree. |
| Postorder Traversal | Visits nodes in this order: Left subtree, Right subtree, Root node. |
| Level-order Traversal (BFS) | Visits nodes level by level from top to bottom. |
In the next topic, we'll explore graphs and hash tables, two more essential data structures in computer science. Graphs are used to model relationships between objects, while hash tables provide efficient key-value storage and retrieval.
Stay tuned for more insights into these powerful data structures!
Tip