DATA STRUCTURE USING C UNIT-4 TREES General trees, Terminology, Representation of trees, Tree traversal- Binary tree, Representation, Expression tree, Binary tree traversal, Threaded Binary Tree, Binary Search Tree: Construction, Searching, Insertion, Deletion, AVL trees: Rotation, Insertion, Deletion, B-Trees, Splay trees, Red-Black Trees, Heap and Heap Sort GENERAL TREES AND TERMINOLOGY: A general tree is a type of data structure that consists of a hierarchy of elements (called nodes) that are connected in a parent-child relationship. In contrast to binary trees (where each node has at most two children), a general tree allows nodes to have an arbitrary number of children. General trees are used in various applications such as representing organizational structures, file systems, and hierarchical databases. Key Terminology: Node: Each element in the tree. A node contains data and may have child nodes. Root: The topmost node in the tree, which has no parent. Child: A node directly connected to another node when moving away from the root. Parent: A node that has one or more child nodes. Leaf: A node that has no children. Sibling: Nodes that share the same parent. Subtree: A portion of the tree that consists of a node and all its descendants. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 1 DATA STRUCTURE USING C Properties of General Trees: Dynamic number of children: Unlike binary trees, nodes in general trees can have any number of children. No specific ordering: There is no inherent order to the children in a general tree unless it is imposed by the problem or structure being modeled. Types of General Trees: 1. N-ary Tree: A general tree where each node has at most N children. 2. Forest: A collection of disjoint trees (i.e., a set of trees). 3. Binary Tree Representation: A general tree can be transformed into a binary tree for ease of manipulation by maintaining left-child and right-sibling relationships. REPRESENTATION OF TREES: SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 2 DATA STRUCTURE USING C In C, trees can be represented using structures (struct) and pointers. The most common representations include binary trees and general trees. TREE TRAVERSAL- BINARY TREE REPRESENTATION: A binary tree is a hierarchical data structure in which each node has at most two children, referred to as the left child and the right child. Binary trees are widely used in computer science for various applications such as searching, sorting, and hierarchical data storage. Key Concepts of a Binary Tree: 1. Node: A fundamental unit of the tree that contains data and may link to other nodes. 2. Root: The topmost node of the binary tree. There is only one root in a tree. 3. Parent and Child: In a tree, a node that has child nodes is called the parent, and the nodes below it are called children. 4. Subtree: A node and all its descendants form a subtree. 5. Leaf Node: A node with no children is called a leaf node. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 3 DATA STRUCTURE USING C 6. Internal Node: Any node with at least one child. 7. Depth: The number of edges from the root to the node. 8. Height: The number of edges on the longest path from the node to a leaf. For a tree, the height of the root is the height of the tree. 9. Level: The level of a node is determined by how far it is from the root (root is at level 0). Types of Binary Trees: 1. Full Binary Tree: Every node has either 0 or 2 children. 2. Complete Binary Tree: All levels are completely filled except possibly for the last, which is filled from left to right. 3. Perfect Binary Tree: All internal nodes have two children, and all leaf nodes are at the same level. 4. Balanced Binary Tree: The height of the tree is as small as possible, generally aiming for a logarithmic height relative to the number of nodes. A balanced binary tree helps maintain efficient search, insert, and delete operations. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 4 DATA STRUCTURE USING C 5. Degenerate (or Pathological) Binary Tree: Each parent node has only one child, resembling a linked list. Traversal Methods: To process or visit nodes in a binary tree, there are several common traversal techniques: 1. Inorder Traversal: Left subtree → Root → Right subtree. o Useful for getting nodes in non-decreasing order in a binary search tree. 2. Preorder Traversal: Root → Left subtree → Right subtree. o Used to create a copy of the tree or get a prefix expression in an expression tree. 3. Postorder Traversal: Left subtree → Right subtree → Root. o Often used to delete the tree or evaluate postfix expressions. 4. Level Order Traversal (Breadth-First): Traverses the tree level by level from left to right. Binary Tree Operations: 1. Insertion: Inserting a node into a binary tree follows specific rules depending on the tree type (e.g., binary search tree). 2. Deletion: Removing a node from the tree, with considerations for node replacement if the node has children. 3. Search: Finding a node in the tree, often efficiently performed in binary search trees. 4. Traversal: Visiting all nodes of the tree in a specific order. EXPRESSION TREE: An expression tree is a binary tree used to represent expressions. In this tree: Operands (like numbers or variables) are represented by leaf nodes. Operators (like +, -, *, /) are represented by internal nodes. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 5 DATA STRUCTURE USING C The expression tree allows us to convert an infix expression (e.g., (a + b) * c) into a structured format that can be more easily evaluated by computers. Here's how an expression tree works: Structure: 1. Leaves: The leaves of the tree contain operands like constants, variables, or numbers. 2. Internal Nodes: The internal nodes contain operators like +, -, *, /. Example: For the arithmetic expression: (a + b) * (c - d) The corresponding expression tree would look like: * /\ + /\ /\ a bc d In this tree: The root is *, indicating multiplication. The left subtree represents the expression (a + b). The right subtree represents the expression (c - d). Types of Traversals: You can evaluate an expression tree using tree traversal methods: In-order traversal: Recovers the original infix expression. Pre-order traversal: Yields the prefix notation (Polish Notation). Post-order traversal: Yields the postfix notation (Reverse Polish Notation), which is useful for stack-based evaluation. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 6 DATA STRUCTURE USING C Applications: Compilers: Used to represent mathematical expressions and perform syntax analysis. Expression evaluation: The tree structure simplifies the order of operations and helps in implementing calculators or parsers for programming languages. BINARY TREE TRAVERSAL: In binary tree traversal, each node is visited in a specific order. There are three main types of depth-first traversals for binary trees: 1. In-order Traversal (Left, Root, Right): Visit the left subtree, then the root, and finally the right subtree. 2. Pre-order Traversal (Root, Left, Right): Visit the root, then the left subtree, and finally the right subtree. 3. Post-order Traversal (Left, Right, Root): Visit the left subtree, then the right subtree, and finally the root. #include <stdio.h> #include <stdlib.h> // Define the structure of a node in the binary tree struct Node { int data; struct Node *left; struct Node *right; }; // Function to create a new node struct Node* createNode(int data) { struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); newNode->data = data; SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 7 DATA STRUCTURE USING C newNode->left = NULL; newNode->right = NULL; return newNode; } // In-order traversal (Left, Root, Right) void inOrder(struct Node* node) { if (node == NULL) return; inOrder(node->left); // Visit left subtree printf("%d ", node->data); // Visit root inOrder(node->right); // Visit right subtree } // Pre-order traversal (Root, Left, Right) void preOrder(struct Node* node) { if (node == NULL) return; printf("%d ", node->data); // Visit root preOrder(node->left); // Visit left subtree preOrder(node->right); // Visit right subtree } // Post-order traversal (Left, Right, Root) void postOrder(struct Node* node) { if (node == NULL) SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 8 DATA STRUCTURE USING C return; postOrder(node->left); // Visit left subtree postOrder(node->right); // Visit right subtree printf("%d ", node->data); // Visit root } // Main function to test the traversal methods int main() { // Creating the binary tree struct Node* root = createNode(1); root->left = createNode(2); root->right = createNode(3); root->left->left = createNode(4); root->left->right = createNode(5); printf("In-order traversal: "); inOrder(root); printf("\n"); printf("Pre-order traversal: "); preOrder(root); printf("\n"); printf("Post-order traversal: "); postOrder(root); printf("\n"); return 0; SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 9 DATA STRUCTURE USING C } OUTPUT 1 /\ 2 3 /\ 4 5 The traversals produce: In-order: 4 2 5 1 3 Pre-order: 1 2 4 5 3 Post-order: 4 5 2 3 1 THREADED BINARY TREE: SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 10 DATA STRUCTURE USING C A threaded binary tree is a variant of the binary tree where "threads" are used to make in-order traversal more efficient. In a regular binary tree, many nodes have NULL pointers for their left or right children (especially leaf nodes). In a threaded binary tree, these NULL pointers are replaced with pointers to the in-order predecessor or in-order successor of the node. There are two types of threaded binary trees: 1. Single-threaded: Only one NULL pointer (either left or right) is replaced with a thread. o Left-threaded: Threads point to the in-order predecessor. o Right-threaded: Threads point to the in-order successor. 2. Fully-threaded: Both NULL pointers are replaced, and each node has threads pointing to both the in-order predecessor and in-order successor if there are no children. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 11 DATA STRUCTURE USING C Motivation: In a regular binary tree, in-order traversal uses a stack or recursion. A threaded binary tree eliminates the need for a stack or recursion by using threads. Traversing from a node to its in-order successor or predecessor becomes more efficient as it avoids the overhead of recursion or additional memory. BINARY SEARCH TREE: CONSTRUCTION, SEARCHING, INSERTION, DELETION: A Binary Search Tree (BST) is a binary tree in which all nodes follow the property: Left Subtree: Contains values less than the root node. Right Subtree: Contains values greater than the root node. This property makes searching, inserting, and deleting elements efficient, with average time complexities of O(log n) Characteristics of BST: Each node has at most two children. Left child nodes hold values less than the node’s value. Right child nodes hold values greater than the node’s value. In-order traversal of a BST gives the elements in sorted order. #include <stdio.h> #include <stdlib.h> // Structure of a node in a Binary Search Tree struct Node { int data; struct Node* left; struct Node* right; SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 12 DATA STRUCTURE USING C }; // Function to create a new node struct Node* createNode(int data) { struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); newNode->data = data; newNode->left = NULL; newNode->right = NULL; return newNode; } // Function to insert a new node in the Binary Search Tree struct Node* insert(struct Node* root, int data) { // If the tree is empty, return a new node if (root == NULL) { return createNode(data); } // Otherwise, recur down the tree if (data < root->data) { root->left = insert(root->left, data); } else if (data > root->data) { root->right = insert(root->right, data); } // Return the unchanged root pointer return root; SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 13 DATA STRUCTURE USING C } // Function to perform in-order traversal of the Binary Search Tree void inOrder(struct Node* root) { if (root != NULL) { inOrder(root->left); // Visit the left subtree printf("%d ", root->data); // Print the data at the root inOrder(root->right); // Visit the right subtree } } // Function to search for a value in the Binary Search Tree struct Node* search(struct Node* root, int key) { // Base case: root is NULL or the key is present at the root if (root == NULL || root->data == key) return root; // If key is smaller than the root's data, search in the left subtree if (key < root->data) return search(root->left, key); // Otherwise, search in the right subtree return search(root->right, key); } // Function to find the minimum value node in the right subtree struct Node* minValueNode(struct Node* node) { struct Node* current = node; SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 14 DATA STRUCTURE USING C // Find the leftmost leaf node (smallest node) while (current && current->left != NULL) current = current->left; return current; } // Function to delete a node from the Binary Search Tree struct Node* deleteNode(struct Node* root, int key) { // Base case if (root == NULL) return root; // Recur down the tree to find the node to be deleted if (key < root->data) { root->left = deleteNode(root->left, key); } else if (key > root->data) { root->right = deleteNode(root->right, key); } else { // Node with only one child or no child if (root->left == NULL) { struct Node* temp = root->right; free(root); return temp; } else if (root->right == NULL) { struct Node* temp = root->left; SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 15 DATA STRUCTURE USING C free(root); return temp; } // Node with two children: get the in-order successor (smallest in the right subtree) struct Node* temp = minValueNode(root->right); // Replace the node's data with the in-order successor's data root->data = temp->data; // Delete the in-order successor root->right = deleteNode(root->right, temp->data); } return root; } // Main function to demonstrate Binary Search Tree operations int main() { struct Node* root = NULL; root = insert(root, 50); root = insert(root, 30); root = insert(root, 20); root = insert(root, 40); root = insert(root, 70); root = insert(root, 60); root = insert(root, 80); SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 16 DATA STRUCTURE USING C printf("In-order traversal of the BST: "); inOrder(root); printf("\n"); printf("Delete 20\n"); root = deleteNode(root, 20); printf("In-order traversal after deletion: "); inOrder(root); printf("\n"); printf("Search for 60: "); struct Node* result = search(root, 60); if (result != NULL) { printf("Found %d\n", result->data); } else { printf("Not found\n"); } return 0; } OUTPUT In-order traversal of the BST: 20 30 40 50 60 70 80 Delete 20 In-order traversal after deletion: 30 40 50 60 70 80 Search for 60: Found 60 SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 17 DATA STRUCTURE USING C Time Complexity: Insertion: O(h) where h is the height of the tree. Search: O(h) where h is the height of the tree. Deletion: O(h) where h is the height of the tree. For a balanced BST, h=O(log n) making these operations efficient. AVL TREES: ROTATION, INSERTION, DELETION: An AVL tree is a type of self-balancing binary search tree (BST) where the difference between heights of left and right subtrees cannot be more than one for all nodes. This balance ensures that the tree's height remains logarithmic with respect to the number of nodes, improving the efficiency of search, insertion, and deletion operations. AVL Tree is invented by GM Adelson - Velsky and EM Landis in 1962. The tree is named AVL in honour of its inventors. AVL Tree can be defined as height balanced binary search tree in which each node is associated with a balance factor which is calculated by subtracting the height of its right sub-tree from that of its left sub-tree. Tree is said to be balanced if balance factor of each node is in between -1 to 1, otherwise, the tree will be unbalanced and need to be balanced. Balance Factor (k) = height (left(k)) - height (right(k)) If balance factor of any node is 1, it means that the left sub-tree is one level higher than the right sub-tree. If balance factor of any node is 0, it means that the left sub-tree and right sub-tree contain equal height. If balance factor of any node is -1, it means that the left sub-tree is one level lower than the right sub-tree. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 18 DATA STRUCTURE USING C An AVL tree is given in the following figure. We can see that, balance factor associated with each node is in between -1 and +1. therefore, it is an example of AVL tree. Complexity Algorithm Average case Worst case Space o(n) o(n) Search o(log n) o(log n) Insert o(log n) o(log n) Delete o(log n) o(log n) Why AVL Tree? AVL tree controls the height of the binary search tree by not letting it to be skewed. The time taken for all operations in a binary search tree of height h SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 19 DATA STRUCTURE USING C is O(h). However, it can be extended to O(n) if the BST becomes skewed (i.e. worst case). By limiting this height to log n, AVL tree imposes an upper bound on each operation to be O(log n) where n is the number of nodes. 1. Rotation in AVL Trees AVL trees use rotations to maintain balance after an insertion or deletion. There are four types of rotations: Right Rotation (RR Rotation) (for left-heavy imbalance) Left Rotation (LL Rotation) (for right-heavy imbalance) Left-Right Rotation (LR Rotation) (for left-right imbalance) Right-Left Rotation (RL Rotation) (for right-left imbalance) 1. RR Rotation When BST becomes unbalanced, due to a node is inserted into the right subtree of the right subtree of A, then we perform RR rotation, RR rotation is an anticlockwise rotation, which is applied on the edge below a node having balance factor -2 In above example, node A has balance factor -2 because a node C is inserted in the right subtree of A right subtree. We perform the RR rotation on the edge below A. 2. LL Rotation When BST becomes unbalanced, due to a node is inserted into the left subtree of the left subtree of C, then we perform LL rotation, LL rotation is clockwise rotation, which is applied on the edge below a node having balance factor 2. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 20 DATA STRUCTURE USING C In above example, node C has balance factor 2 because a node A is inserted in the left subtree of C left subtree. We perform the LL rotation on the edge below A. 3. LR Rotation Double rotations are bit tougher than single rotation which has already explained above. LR rotation = RR rotation + LL rotation, i.e., first RR rotation is performed on subtree and then LL rotation is performed on full tree, by full tree we mean the first node from the path of inserted node whose balance factor is other than -1, 0, or 1. Let us understand each and every step very clearly: State Action A node B has been inserted into the right subtree of A the left subtree of C, because of which C has become an unbalanced node having balance factor 2. This case is L R rotation where: Inserted node is in the right subtree of left subtree of C SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 21 DATA STRUCTURE USING C As LR rotation = RR + LL rotation, hence RR (anticlockwise) on subtree rooted at A is performed first. By doing RR rotation, node A, has become the left subtree of B. After performing RR rotation, node C is still unbalanced, i.e., having balance factor 2, as inserted node A is in the left of left of C Now we perform LL clockwise rotation on full tree, i.e. on node C. node C has now become the right subtree of node B, A is left subtree of B Balance factor of each node is now either -1, 0, or 1, i.e. BST is balanced now. 4. RL Rotation As already discussed, that double rotations are bit tougher than single rotation which has already explained above. R L rotation = LL rotation + RR rotation, i.e., first LL rotation is performed on subtree and then RR rotation is performed on full SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 22 DATA STRUCTURE USING C tree, by full tree we mean the first node from the path of inserted node whose balance factor is other than -1, 0, or 1. State Action A node B has been inserted into the left subtree of C the right subtree of A, because of which A has become an unbalanced node having balance factor - 2. This case is RL rotation where: Inserted node is in the left subtree of right subtree of A As RL rotation = LL rotation + RR rotation, hence, LL (clockwise) on subtree rooted at C is performed first. By doing RR rotation, node C has become the right subtree of B. After performing LL rotation, node A is still unbalanced, i.e. having balance factor -2, which is because of the right-subtree of the right-subtree node A. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 23 DATA STRUCTURE USING C Now we perform RR rotation (anticlockwise rotation) on full tree, i.e. on node A. node C has now become the right subtree of node B, and node A has become the left subtree of B. Balance factor of each node is now either -1, 0, or 1, i.e., BST is balanced now. B-TREES: The limitations of traditional binary search trees can be frustrating. Meet the BTree, the multi-talented data structure that can handle massive amounts of data with ease. When it comes to storing and searching large amounts of data, traditional binary search trees can become impractical due to their poor performance and high memory usage. B-Trees, also known as B-Tree or Balanced Tree, are a type of self-balancing tree that was specifically designed to overcome these limitations. Unlike traditional binary search trees, B-Trees are characterized by the large number of keys that they can store in a single node, which is why they are also known as “large key” trees. Each node in a B-Tree can contain multiple keys, which allows the tree to have a larger branching factor and thus a shallower height. This shallow height leads to less disk I/O, which results in faster search and insertion operations. B-Trees are particularly well suited for storage systems that have slow, bulky data access such as hard drives, flash memory, and CDROMs. B-Trees maintains balance by ensuring that each node has a minimum number of keys, so the tree is always balanced. This balance guarantees that the time SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 24 DATA STRUCTURE USING C complexity for operations such as insertion, deletion, and searching is always O(log n), regardless of the initial shape of the tree. Time Complexity of B-Tree: Sr. No. Algorithm Time Complexity 1. Search O(log n) 2. Insert O(log n) 3. Delete O(log n) Note: “n” is the total number of elements in the B-tree Properties of B-Tree: All leaves are at the same level. B-Tree is defined by the term minimum degree ‘t‘. The value of ‘t‘ depends upon disk block size. Every node except the root must contain at least t-1 keys. The root may contain a minimum of 1 key. All nodes (including root) may contain at most (2*t – 1) keys. Number of children of a node is equal to the number of keys in it plus 1. All keys of a node are sorted in increasing order. The child between two keys k1 and k2 contains all keys in the range from k1 and k2. B-Tree grows and shrinks from the root which is unlike Binary Search Tree. Binary Search Trees grow downward and also shrink from downward. Like other balanced Binary Search Trees, the time complexity to search, insert, and delete is O(log n). Insertion of a Node in B-Tree happens only at Leaf Node. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 25 DATA STRUCTURE USING C ALGORITHM The algorithm for B-trees in C involves defining the structure of the tree, handling node insertion, splitting full nodes, and ensuring the properties of the B-tree are maintained (i.e., it remains balanced). Here's a breakdown of the main steps in the algorithm for inserting into a B-tree, as well as the high-level concepts for search and splitting operations. B-Tree Algorithm Overview 1. Structure of a B-Tree Node A B-tree node typically contains: Keys: An array of keys stored in sorted order. Children: An array of pointers to child nodes. Leaf flag: A flag indicating whether the node is a leaf or an internal node. Number of keys: The current number of keys in the node. 2. B-Tree Insertion Algorithm The process for inserting a key into a B-tree involves finding the correct position for the key, inserting it, and potentially splitting a full node to maintain B-tree properties. Insertion Steps: 1. Start at the root: If the root is full, a split is required. 2. Recursively find the appropriate child for the new key. 3. Insert the key into a non-full node. If the node has space, place the key in the correct sorted position within the node. 4. Split the node if it's full: SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 26 DATA STRUCTURE USING C Split the full node into two nodes. o Move the middle key up to the parent node. 5. Adjust the tree: Ensure the tree remains balanced by splitting nodes and propagating changes up if necessary. o 3. B-Tree Search Algorithm Searching in a B-tree is similar to binary search but works with multiple keys and children in each node. Start at the root, comparing the key with keys in the current node. If the key is found, return success. If the key is smaller or larger than the keys in the node, move to the appropriate child and repeat the process. If the node is a leaf and the key is not found, return failure. Detailed B-Tree Insertion Algorithm (with Splitting) 1. Insert (k, root): o If the root is full, create a new root and split the current root into two nodes, then insert the middle key into the new root. o Else, insert k into the root or one of its children recursively, ensuring that splits happen when necessary. 2. InsertNonFull (x, k): o If x is a leaf, insert k into the node at the correct position. o If x is an internal node: Find the child of x that should contain k. If the child is full, split it and adjust the parent node. Insert k into the appropriate child after the split. 3. SplitChild (x, i, y): o Create a new node z which will contain the right half of the keys from y. o Move the middle key of y up to the parent node x. o Adjust the children pointers to ensure the tree structure is maintained. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 27 DATA STRUCTURE USING C Algorithm Steps for B-Trees Step 1: Insert a Key into a B-Tree 1. Start from the root: o If the root is not full, insert the key into the correct position. o If the root is full, split the root, create a new root, and proceed. 2. Traverse the tree recursively to find the correct position for the new key. o At each internal node, find the child that should contain the key (i.e., the key lies between two keys in the node). o If the child is full, split it, and then continue with the insertion. 3. Insert the key into the leaf: o Once a leaf node is reached, insert the key in the correct sorted position within the node. Step 2: Split a Node 1. Create a new node z: o Move the second half of the keys from the full node y into z. o If y is not a leaf, move the corresponding child pointers to z as well. 2. Move the middle key of y up to the parent: o The middle key becomes a key in the parent node, ensuring the parent stays sorted. 3. Adjust child pointers: o The parent node now has one additional child (the new node z), and the keys and children are adjusted accordingly. Example of B-Tree Insertion Algorithm 1. Insert 10 into an empty tree: o Create a root node with one key: 10. 2. Insert 20: o Insert 20 into the root node, keeping the keys sorted: [10, 20]. 3. Insert 5: o Insert 5 into the root node, keeping the keys sorted: [5, 10, 20]. 4. Insert 6 (assuming the maximum number of keys is 3): o Insert 6 into the root, resulting in [5, 6, 10, 20], but the root is now full. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 28 DATA STRUCTURE USING C o Split the root: Move 10 to the new root. The left child contains [5, 6], and the right child contains [20]. SPLAY TREES: Splay Trees are a type of self-adjusting binary search tree (BST) where recently accessed elements are moved to the root through a process called "splaying." This provides an advantage in cases where some elements are accessed more frequently than others, as those elements will be quicker to access after being moved closer to the root. Splay trees perform basic operations such as insertion, deletion, and search in an amortized time complexity of O(logn)O(\log n)O(logn). Key Features of Splay Trees: 1. Self-adjusting: After each access, the tree is restructured so that the accessed node is moved to the root. 2. No balance guarantee: Unlike AVL or Red-Black trees, splay trees are not balanced, but their performance is efficient in the long run. 3. Amortized O(logn)O(\log n)O(logn): Even though individual operations can take linear time in the worst case, the average time complexity over a sequence of operations is logarithmic. Key Operations in a Splay Tree: 1. Search: After searching for a node, the found node is splayed to the root. 2. Insertion: The inserted node is splayed to the root. 3. Deletion: After deleting a node, the tree is splayed to bring the deleted node’s parent to the root. Splay Tree Rotations: The core idea of a splay tree is based on rotations. There are three types of rotations involved in the splaying process: 1. Zig Rotation: This is a single right or left rotation, used when the node being accessed is a child of the root. 2. Zig-Zig Rotation: This double rotation occurs when the node and its parent are both either left or right children (left-left or right-right case). 3. Zig-Zag Rotation: This double rotation occurs when the node is a left child, and its parent is a right child, or vice versa (left-right or right-left case). SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 29 DATA STRUCTURE USING C Splaying Operation: Splaying is the process of bringing the accessed node to the root using the three types of rotations mentioned above. Splaying is done recursively, from the accessed node to the root. Splay Tree Operations Algorithm: 1. Splay Operation The splay operation moves a node to the root by performing the appropriate rotations. 1. Zig case (Single rotation): o If the node is a direct child of the root, perform a single rotation (either left or right) to make it the root. 2. Zig-Zig case (Double rotation): o If both the node and its parent are either left children or right children of their respective parents, perform two rotations in the same direction to bring the node to the root. 3. Zig-Zag case (Double rotation): o If the node is a left child and its parent is a right child (or vice versa), perform a zig-zag rotation (first rotate in one direction and then in the opposite direction) to move the node closer to the root. 2. Insertion in a Splay Tree To insert a node into a splay tree: Perform a regular binary search tree insertion. After inserting, splay the newly inserted node to the root. 3. Search in a Splay Tree To search for a node in a splay tree: Perform a regular binary search. If the node is found, splay it to the root. If the node is not found, splay the last accessed node (the potential parent). SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 30 DATA STRUCTURE USING C 4. Deletion in a Splay Tree To delete a node from a splay tree: Splay the node to the root. After deletion, two subtrees are left. The left subtree contains all the nodes smaller than the deleted node, and the right subtree contains all the nodes greater than the deleted node. The left subtree is then splayed so that its maximum node becomes the root, and this subtree is merged with the right subtree. RED-BLACK TREES: The red-Black tree is a binary search tree. The prerequisite of the red-black tree is that we should know about the binary search tree. In a binary search tree, the values of the nodes in the left subtree should be less than the value of the root node, and the values of the nodes in the right subtree should be greater than the value of the root node. Each node in the Red-black tree contains an extra bit that represents a color to ensure that the tree is balanced during any operations performed on the tree like insertion, deletion, etc. In a binary search tree, the searching, insertion and deletion take O(log2n) time in the average case, O(1) in the best case and O(n) in the worst case. Let's understand the different scenarios of a binary search tree. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 31 DATA STRUCTURE USING C In the above tree, if we want to search the 80. We will first compare 80 with the root node. 80 is greater than the root node, i.e., 10, so searching will be performed on the right subtree. Again, 80 is compared with 15; 80 is greater than 15, so we move to the right of the 15, i.e., 20. Now, we reach the leaf node 20, and 20 is not equal to 80. Therefore, it will show that the element is not found in the tree. After each operation, the search is divided into half. The above BST will take O(logn) time to search the element. Advertisement SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 32 DATA STRUCTURE USING C The above tree shows the right-skewed BST. If we want to search the 80 in the tree, we will compare 80 with all the nodes until we find the element or reach the leaf node. So, the above right-skewed BST will take O(N) time to search the element. In the above BST, the first one is the balanced BST, whereas the second one is the unbalanced BST. We conclude from the above two binary search trees that a balanced tree takes less time than an unbalanced tree for performing any operation on the tree. Therefore, we need a balanced tree, and the Red-Black tree is a self-balanced binary search tree. Now, the question arises that why do we require a Red-Black tree if AVL is also a height-balanced tree. The Red-Black tree is used because the AVL tree requires many rotations when the tree is large, whereas the Red-Black tree requires a maximum of two rotations to balance the tree. The main difference between the AVL tree and the Red-Black tree is that the AVL tree is strictly balanced, while the Red-Black tree is not completely height-balanced. So, the AVL tree is more balanced than the Red-Black tree, but the Red-Black tree guarantees O(log2n) time for all operations like insertion, deletion, and searching. Insertion is easier in the AVL tree as the AVL tree is strictly balanced, whereas deletion and searching are easier in the Red-Black tree as the Red-Black tree requires fewer rotations. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 33 DATA STRUCTURE USING C As the name suggests that the node is either colored in Red or Black color. Sometimes no rotation is required, and only recoloring is needed to balance the tree. Properties of Red-Black tree o o o o o o It is a self-balancing Binary Search tree. Here, self-balancing means that it balances the tree itself by either doing the rotations or recoloring the nodes. This tree data structure is named as a Red-Black tree as each node is either Red or Black in color. Every node stores one extra information known as a bit that represents the color of the node. For example, 0 bit denotes the black color while 1 bit denotes the red color of the node. Other information stored by the node is similar to the binary tree, i.e., data part, left pointer and right pointer. In the Red-Black tree, the root node is always black in color. In a binary tree, we consider those nodes as the leaf which have no child. In contrast, in the Red-Black tree, the nodes that have no child are considered the internal nodes and these nodes are connected to the NIL nodes that are always black in color. The NIL nodes are the leaf nodes in the Red-Black tree. If the node is Red, then its children should be in Black color. In other words, we can say that there should be no red-red parent-child relationship. Every path from a node to any of its descendant's NIL node should have same number of black nodes. Is every AVL tree can be a Red-Black tree? Yes, every AVL tree can be a Red-Black tree if we color each node either by Red or Black color. But every Red-Black tree is not an AVL because the AVL tree is strictly height-balanced while the Red-Black tree is not completely heightbalanced. Insertion in Red Black tree The following are some rules used to create the Red-Black tree: 1. If the tree is empty, then we create a new node as a root node with the color black. 2. If the tree is not empty, then we create a new node as a leaf node with a color red. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 34 DATA STRUCTURE USING C 3. If the parent of a new node is black, then exit. 4. If the parent of a new node is Red, then we have to check the color of the parent's sibling of a new node. 4a) If the color is Black, then we perform rotations and recoloring. 4b) If the color is Red then we recolor the node. We will also check whether the parents' parent of a new node is the root node or not; if it is not a root node, we will recolor and recheck the node. Let's understand the insertion in the Red-Black tree. 10, 18, 7, 15, 16, 30, 25, 40, 60 Step 1: Initially, the tree is empty, so we create a new node having value 10. This is the first node of the tree, so it would be the root node of the tree. As we already discussed, that root node must be black in color, which is shown below: Step 2: The next node is 18. As 18 is greater than 10 so it will come at the right of 10 as shown below. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 35 DATA STRUCTURE USING C We know the second rule of the Red Black tree that if the tree is not empty then the newly created node will have the Red color. Therefore, node 18 has a Red color, as shown in the below figure: Now we verify the third rule of the Red-Black tree, i.e., the parent of the new node is black or not. In the above figure, the parent of the node is black in color; therefore, it is a Red-Black tree. Step 3: Now, we create the new node having value 7 with Red color. As 7 is less than 10, so it will come at the left of 10 as shown below. Advertisement Now we verify the third rule of the Red-Black tree, i.e., the parent of the new node is black or not. As we can observe, the parent of the node 7 is black in color, and it obeys the Red-Black tree's properties. Step 4: The next element is 15, and 15 is greater than 10, but less than 18, so the new node will be created at the left of node 18. The node 15 would be Red in color as the tree is not empty. The above tree violates the property of the Red-Black tree as it has Red-red parentchild relationship. Now we have to apply some rule to make a Red-Black tree. The rule 4 says that if the new node's parent is Red, then we have to check the color of the parent's sibling of a new node. The new node is node 15; the parent of the new node is node 18 and the sibling of the parent node is node 7. As the color of the parent's sibling is Red in color, so we apply the rule 4a. The rule 4a says that we have to recolor both the parent and parent's sibling node. So, both the nodes, i.e., 7 and 18, would be recolored as shown in the below figure. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 36 DATA STRUCTURE USING C We also have to check whether the parent's parent of the new node is the root node or not. As we can observe in the above figure, the parent's parent of a new node is the root node, so we do not need to recolor it. Step 5: The next element is 16. As 16 is greater than 10 but less than 18 and greater than 15, so node 16 will come at the right of node 15. The tree is not empty; node 16 would be Red in color, as shown in the below figure: SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 37 DATA STRUCTURE USING C In the above figure, we can observe that it violates the property of the parent-child relationship as it has a red-red parent-child relationship. We have to apply some rules to make a Red-Black tree. Since the new node's parent is Red color, and the parent of the new node has no sibling, so rule 4a will be applied. The rule 4a says that some rotations and recoloring would be performed on the tree. Since node 16 is right of node 15 and the parent of node 15 is node 18. Node 15 is the left of node 18. Here we have an LR relationship, so we require to perform two rotations. First, we will perform left, and then we will perform the right rotation. The left rotation would be performed on nodes 15 and 16, where node 16 will move upward, and node 15 will move downward. Once the left rotation is performed, the tree looks like as shown in the below figure: SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 38 DATA STRUCTURE USING C In the above figure, we can observe that there is an LL relationship. The above tree has a Red-red conflict, so we perform the right rotation. When we perform the right rotation, the median element would be the root node. Once the right rotation is performed, node 16 would become the root node, and nodes 15 and 18 would be the left child and right child, respectively, as shown in the below figure. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 39 DATA STRUCTURE USING C After rotation, node 16 and node 18 would be recolored; the color of node 16 is red, so it will change to black, and the color of node 18 is black, so it will change to a red color as shown in the below figure: SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 40 DATA STRUCTURE USING C Step 6: The next element is 30. Node 30 is inserted at the right of node 18. As the tree is not empty, so the color of node 30 would be red. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 41 DATA STRUCTURE USING C The color of the parent and parent's sibling of a new node is Red, so rule 4b is applied. In rule 4b, we have to do only recoloring, i.e., no rotations are required. The color of both the parent (node 18) and parent's sibling (node 15) would become black, as shown in the below image. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 42 DATA STRUCTURE USING C We also have to check the parent's parent of the new node, whether it is a root node or not. The parent's parent of the new node, i.e., node 30 is node 16 and node 16 is not a root node, so we will recolor the node 16 and changes to the Red color. The parent of node 16 is node 10, and it is not in Red color, so there is no Red-red conflict. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 43 DATA STRUCTURE USING C Step 7: The next element is 25, which we have to insert in a tree. Since 25 is greater than 10, 16, 18 but less than 30; so, it will come at the left of node 30. As the tree is not empty, node 25 would be in Red color. Here Red-red conflict occurs as the parent of the newly created is Red color. Since there is no parent's sibling, so rule 4a is applied in which rotation, as well as recoloring, are performed. First, we will perform rotations. As the newly created node is at the left of its parent and the parent node is at the right of its parent, so the RL relationship is formed. Firstly, the right rotation is performed in which node 25 goes upwards, whereas node 30 goes downwards, as shown in the below figure. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 44 DATA STRUCTURE USING C After the first rotation, there is an RR relationship, so left rotation is performed. After right rotation, the median element, i.e., 25 would be the root node; node 30 would be at the right of 25 and node 18 would be at the left of node 25. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 45 DATA STRUCTURE USING C Now recoloring would be performed on nodes 25 and 18; node 25 becomes black in color, and node 18 becomes red in color. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 46 DATA STRUCTURE USING C Step 8: The next element is 40. Since 40 is greater than 10, 16, 18, 25, and 30, so node 40 will come at the right of node 30. As the tree is not empty, node 40 would be Red in color. There is a Red-red conflict between nodes 40 and 30, so rule 4b will be applied. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 47 DATA STRUCTURE USING C As the color of parent and parent's sibling node of a new node is Red so recoloring would be performed. The color of both the nodes would become black, as shown in the below image. After recoloring, we also have to check the parent's parent of a new node, i.e., 25, which is not a root node, so recoloring would be performed, and the color of node 25 changes to Red. After recoloring, red-red conflict occurs between nodes 25 and 16. Now node 25 would be considered as the new node. Since the parent of node 25 is red in color, and the parent's sibling is black in color, rule 4a would be applied. Since 25 is at the right of the node 16 and 16 is at the right of its parent, so there is an RR relationship. In the RR relationship, left rotation is performed. After left rotation, the median element 16 would be the root node, as shown in the below figure. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 48 DATA STRUCTURE USING C After rotation, recoloring is performed on nodes 16 and 10. The color of node 10 and node 16 changes to Red and Black, respectively as shown in the below figure. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 49 DATA STRUCTURE USING C Step 9: The next element is 60. Since 60 is greater than 16, 25, 30, and 40, so node 60 will come at the right of node 40. As the tree is not empty, the color of node 60 would be Red. As we can observe in the above tree that there is a Red-red conflict occurs. The parent node is Red in color, and there is no parent's sibling exists in the tree, so rule 4a would be applied. The first rotation would be performed. The RR relationship exists between the nodes, so left rotation would be performed. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 50 DATA STRUCTURE USING C When left rotation is performed, node 40 will come upwards, and node 30 will come downwards, as shown in the below figure: After rotation, the recoloring is performed on nodes 30 and 40. The color of node 30 would become Red, while the color of node 40 would become black. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 51 DATA STRUCTURE USING C The above tree is a Red-Black tree as it follows all the Red-Black tree properties. Deletion in Red Back tree Let's understand how we can delete the particular node from the Red-Black tree. The following are the rules used to delete the particular node from the tree: Step 1: First, we perform BST rules for the deletion. Step 2: Case 1: if the node is Red, which is to be deleted, we simply delete it. Let's understand case 1 through an example. Suppose we want to delete node 30 from the tree, which is given below. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 52 DATA STRUCTURE USING C Initially, we are having the address of the root node. First, we will apply BST to search the node. Since 30 is greater than 10 and 20, which means that 30 is the right child of node 20. Node 30 is a leaf node and Red in color, so it is simply deleted from the tree. If we want to delete the internal node that has one child. First, replace the value of the internal node with the value of the child node and then simply delete the child node. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 53 DATA STRUCTURE USING C We cannot delete the internal node; we can only replace the value of that node with another value. Node 20 is at the right of the root node, and it is having only one child, node 30. So, node 20 is replaced with a value 30, but the color of the node would remain the same, i.e., Black. In the end, node 20 (leaf node) is deleted from the tree. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 54 DATA STRUCTURE USING C If we want to delete the internal node that has two child nodes. In this case, we have to decide from which we have to replace the value of the internal node (either left subtree or right subtree). We have two ways: o o Inorder predecessor: We will replace with the largest value that exists in the left subtree. Inorder successor: We will replace with the smallest value that exists in the right subtree. Suppose we want to delete node 30 from the tree, which is shown below: SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 55 DATA STRUCTURE USING C Node 30 is at the right of the root node. In this case, we will use the inorder successor. The value 38 is the smallest value in the right subtree, so we will replace the value 30 with 38, but the node would remain the same, i.e., Red. After replacement, the leaf node, i.e., 30, would be deleted from the tree. Since node 30 is a leaf node and Red in color, we need to delete it (we do not have to perform any rotations or any recoloring). Case 2: If the root node is also double black, then simply remove the double black and make it a single black. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 56 DATA STRUCTURE USING C Case 3: If the double black's sibling is black and both its children are black. o o Remove the double black node. Add the color of the node to the parent (P) node. 1. If the color of P is red then it becomes black. 2. If the color of P is black, then it becomes double black. o o The color of double black's sibling changes to red. If still double black situation arises, then we will apply other cases. Let's understand this case through an example. Suppose we want to delete node 15 in the below tree. We cannot simply delete node 15 from the tree as node 15 is Black in color. Node 15 has two children, which are nil. So, we replace the 15 value with a nil value. As node 15 and nil node are black in color, the node becomes double black after replacement, as shown in the below figure. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 57 DATA STRUCTURE USING C In the above tree, we can observe that the double black's sibling is black in color and its children are nil, which are also black. As the double black's sibling and its children have black so it cannot give its black color to neither of these. Now, the double black's parent node is Red so double black's node add its black color to its parent node. The color of the node 20 changes to black while the color of the nil node changes to a single black as shown in the below figure. After adding the color to its parent node, the color of the double black's sibling, i.e., node 30 changes to red as shown in the below figure. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 58 DATA STRUCTURE USING C In the above tree, we can observe that there is no longer double black's problem exists, and it is also a Red-Black tree. Case 4: If double black's sibling is Red. o o o Swap the color of its parent and its sibling. Rotate the parent node in the double black's direction. Reapply cases. Let's understand this case through an example. Suppose we want to delete node 15. Initially, the 15 is replaced with a nil value. After replacement, the node becomes double black. Since double black's sibling is Red so color of the node 20 changes to Red and the color of the node 30 changes to Black. Once the swapping of the color is completed, the rotation towards the double black would be performed. The node 30 will move upwards and the node 20 will move downwards as shown in the below figure. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 59 DATA STRUCTURE USING C In the above tree, we can observe that double black situation still exists in the tree. It satisfies the case 3 in which double black's sibling is black as well as both its children are black. First, we remove the double black from the node and add the black color to its parent node. At the end, the color of the double black's sibling, i.e., node 25 changes to Red as shown in the below figure. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 60 DATA STRUCTURE USING C In the above tree, we can observe that the double black situation has been resolved. It also satisfies the properties of the Red Black tree. Case 5: If double black's sibling is black, sibling's child who is far from the double black is black, but near child to double black is red. o o o Swap the color of double black's sibling and the sibling child which is nearer to the double black node. Rotate the sibling in the opposite direction of the double black. Apply case 6 Suppose we want to delete the node 1 in the below tree. First, we replace the value 1 with the nil value. The node becomes double black as both the nodes, i.e., 1 and nil are black. It satisfies the case 3 that implies if DB's sibling is black and both its children are black. First, we remove the double black of the nil node. Since the parent of DB is Black, so when the black color is added to the parent node then it becomes double black. After adding the color, the double black's sibling color changes to Red as shown below. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 61 DATA STRUCTURE USING C We can observe in the above screenshot that the double black problem still exists in the tree. So, we will reapply the cases. We will apply case 5 because the sibling of node 5 is node 30, which is black in color, the child of node 30, which is far from node 5 is black, and the child of the node 30 which is near to node 5 is Red. In this case, first we will swap the color of node 30 and node 25 so the color of node 30 changes to Red and the color of node 25 changes to Black as shown below. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 62 DATA STRUCTURE USING C Once the swapping of the color between the nodes is completed, we need to rotate the sibling in the opposite direction of the double black node. In this rotation, the node 30 moves downwards while the node 25 moves upwards as shown below. As we can observe in the above tree that double black situation still exists. So, we need to case 6. Let's first see what is case 6. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 63 DATA STRUCTURE USING C Case 6: If double black's sibling is black, far child is Red o o o o Swap the color of Parent and its sibling node. Rotate the parent towards the Double black's direction Remove Double black Change the Red color to black. Now we will apply case 6 in the above example to solve the double black's situation. In the above example, the double black is node 5, and the sibling of node 5 is node 25, which is black in color. The far child of the double black node is node 30, which is Red in color as shown in the below figure: First, we will swap the colors of Parent and its sibling. The parent of node 5 is node 10, and the sibling node is node 25. The colors of both the nodes are black, so there is no swapping would occur. In the second step, we need to rotate the parent in the double black's direction. After rotation, node 25 will move upwards, whereas node 10 will move downwards. Once the rotation is performed, the tree would like, as shown in the below figure: SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 64 DATA STRUCTURE USING C In the next step, we will remove double black from node 5 and node 5 will give its black color to the far child, i.e., node 30. Therefore, the color of node 30 changes to black as shown in the below figure. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 65 DATA STRUCTURE USING C HEAP AND HEAP SORT: What is a heap? A heap is a complete binary tree, and the binary tree is a tree in which the node can have the utmost two children. A complete binary tree is a binary tree in which all the levels except the last level, i.e., leaf node, should be completely filled, and all the nodes should be left-justified. What is heap sort? Heapsort is a popular and efficient sorting algorithm. The concept of heap sort is to eliminate the elements one by one from the heap part of the list, and then insert them into the sorted part of the list. Working of Heap sort Algorithm Now, let's see the working of the Heapsort Algorithm. n heap sort, basically, there are two phases involved in the sorting of elements. By using the heap sort algorithm, they are as follows o o The first step includes the creation of a heap by adjusting the elements of the array. After the creation of heap, now remove the root element of the heap repeatedly by shifting it to the end of the array, and then store the heap structure with the remaining elements. Now let's see the working of heap sort in detail by using an example. To understand it more clearly, let's take an unsorted array and try to sort it using heap sort. It will make the explanation clearer and easier. First, we have to construct a heap from the given array and convert it into max heap. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 66 DATA STRUCTURE USING C After converting the given heap into max heap, the array elements are - Next, we have to delete the root element (89) from the max heap. To delete this node, we have to swap it with the last node, i.e. (11). After deleting the root element, we again have to heapify it to convert it into max heap. After swapping the array element 89 with 11, and converting the heap into maxheap, the elements of array are - SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 67 DATA STRUCTURE USING C In the next step, again, we have to delete the root element (81) from the max heap. To delete this node, we have to swap it with the last node, i.e. (54). After deleting the root element, we again have to heapify it to convert it into max heap. After swapping the array element 81 with 54 and converting the heap into maxheap, the elements of array are - In the next step, we have to delete the root element (76) from the max heap again. To delete this node, we have to swap it with the last node, i.e. (9). After deleting the root element, we again have to heapify it to convert it into max heap. After swapping the array element 76 with 9 and converting the heap into maxheap, the elements of array are - SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 68 DATA STRUCTURE USING C In the next step, again we have to delete the root element (54) from the max heap. To delete this node, we have to swap it with the last node, i.e. (14). After deleting the root element, we again have to heapify it to convert it into max heap. After swapping the array element 54 with 14 and converting the heap into maxheap, the elements of array are - Advertisement In the next step, again we have to delete the root element (22) from the max heap. To delete this node, we have to swap it with the last node, i.e. (11). After deleting the root element, we again have to heapify it to convert it into max heap. SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 69 DATA STRUCTURE USING C After swapping the array element 22 with 11 and converting the heap into maxheap, the elements of array are - In the next step, again we have to delete the root element (14) from the max heap. To delete this node, we have to swap it with the last node, i.e. (9). After deleting the root element, we again have to heapify it to convert it into max heap. After swapping the array element 14 with 9 and converting the heap into maxheap, the elements of array are - In the next step, again we have to delete the root element (11) from the max heap. To delete this node, we have to swap it with the last node, i.e. (9). After deleting the root element, we again have to heapify it to convert it into max heap. After swapping the array element 11 with 9, the elements of array are - SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 70 DATA STRUCTURE USING C Advertisement Advertisement Now, heap has only one element left. After deleting it, heap will be empty. After completion of sorting, the array elements are - Now, the array is completely sorted. Heap sort complexity Now, let's see the time complexity of Heap sort in the best case, average case, and worst case. We will also see the space complexity of Heapsort. 1. Time Complexity Case Time Complexity Best Case O(n logn) Average Case O(n log n) Worst Case O(n log n) SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 71 DATA STRUCTURE USING C o o o Best Case Complexity - It occurs when there is no sorting required, i.e. the array is already sorted. The best-case time complexity of heap sort is O(n logn). Average Case Complexity - It occurs when the array elements are in jumbled order that is not properly ascending and not properly descending. The average case time complexity of heap sort is O(n log n). Worst Case Complexity - It occurs when the array elements are required to be sorted in reverse order. That means suppose you have to sort the array elements in ascending order, but its elements are in descending order. The worst-case time complexity of heap sort is O(n log n). The time complexity of heap sort is O(n logn) in all three cases (best case, average case, and worst case). The height of a complete binary tree having n elements is logn. 2. Space Complexity o Space Complexity O(1) Stable N0 The space complexity of Heap sort is O(1). SRMUH/CSE/Dr. Saroj Kumar Gupta(PhD, PostDoc*) Page 72