|
| 1 | +<h1 align='center'>Convert - BST - To - Max Heap</h1> |
| 2 | + |
| 3 | +## Problem Statement |
| 4 | + |
| 5 | +**Problem URL :** [Convert BST to Max Heap](https://www.geeksforgeeks.org/convert-bst-to-max-heap/) |
| 6 | + |
| 7 | +## Problem Explanation |
| 8 | +The goal of the problem is to **convert a Binary Search Tree (BST) into a Max Heap**. A Max Heap is a binary tree where: |
| 9 | +- The value of each node is greater than or equal to the values of its children. |
| 10 | +- The tree follows the **complete binary tree** property, meaning that all levels of the tree are fully filled except possibly for the last one, which is filled from left to right. |
| 11 | + |
| 12 | +On the other hand, a **Binary Search Tree (BST)** is a binary tree where: |
| 13 | +- For each node, its left child’s value is smaller than its own value, and its right child’s value is greater than its own value. |
| 14 | + |
| 15 | +#### Task: |
| 16 | +Given a **BST**, we need to rearrange its nodes to form a **Max Heap** such that: |
| 17 | +1. The tree must follow the Max Heap property. |
| 18 | +2. The binary tree must be complete (filled from left to right). |
| 19 | + |
| 20 | +#### Example: |
| 21 | +Consider the following BST: |
| 22 | +``` |
| 23 | + 4 |
| 24 | + / \ |
| 25 | + 2 6 |
| 26 | + / \ / \ |
| 27 | + 1 3 5 7 |
| 28 | +``` |
| 29 | +Here, the tree is a Binary Search Tree, and we need to convert it into a Max Heap. |
| 30 | + |
| 31 | +#### Approach: |
| 32 | +To achieve this conversion, we will use the following steps: |
| 33 | +1. **In-order Traversal of BST**: This traversal will give us the values in sorted order. |
| 34 | +2. **Max Heap Property**: We will assign the largest values from the sorted list to the tree nodes, starting from the root, and then recursively assign values to the children, ensuring the Max Heap property is satisfied. |
| 35 | +3. **Recursion**: Starting from the root node, we assign the largest value to it and then recursively apply the same process to the left and right subtrees. This ensures that the largest values are assigned to the root and then propagated down to the leaf nodes. |
| 36 | + |
| 37 | +### Example Walkthrough of Approach: |
| 38 | + |
| 39 | +- For the given BST: |
| 40 | + ``` |
| 41 | + 4 |
| 42 | + / \ |
| 43 | + 2 6 |
| 44 | + / \ / \ |
| 45 | + 1 3 5 7 |
| 46 | + ``` |
| 47 | + |
| 48 | +- Perform **in-order traversal** on the BST: `[1, 2, 3, 4, 5, 6, 7]`. |
| 49 | +- The largest element (7) should be placed at the root, and then we continue filling the tree in the same way: |
| 50 | + ``` |
| 51 | + 7 |
| 52 | + / \ |
| 53 | + 6 5 |
| 54 | + / \ / \ |
| 55 | + 1 3 2 4 |
| 56 | + ``` |
| 57 | + |
| 58 | +Thus, we have successfully converted the BST into a Max Heap. |
| 59 | + |
| 60 | +## Problem Solution |
| 61 | +```cpp |
| 62 | +#include <iostream> |
| 63 | +#include <vector> |
| 64 | +using namespace std; |
| 65 | + |
| 66 | +// Definition for a Node in the Binary Tree |
| 67 | +class Node { |
| 68 | +public: |
| 69 | + int data; // Value of the node |
| 70 | + Node* left; // Left child |
| 71 | + Node* right; // Right child |
| 72 | + |
| 73 | + // Constructor to create a new node with a given value |
| 74 | + Node(int val) { |
| 75 | + this->data = val; |
| 76 | + this->left = NULL; // Initially, left child is NULL |
| 77 | + this->right = NULL; // Initially, right child is NULL |
| 78 | + } |
| 79 | +}; |
| 80 | + |
| 81 | +// Function to perform in-order traversal of the BST |
| 82 | +// This will store the values of the tree nodes in an array |
| 83 | +void inOrder(Node* root, vector<int> &nodes) { |
| 84 | + if (root == NULL) return; // Base case: if node is NULL, return |
| 85 | + |
| 86 | + inOrder(root->left, nodes); // Recur on the left child |
| 87 | + nodes.push_back(root->data); // Store the current node's data |
| 88 | + inOrder(root->right, nodes); // Recur on the right child |
| 89 | +} |
| 90 | + |
| 91 | +// Function to convert the BST to a Max Heap |
| 92 | +// It uses the in-order traversal values stored in 'nodes' and sets the tree |
| 93 | +// values in a way that satisfies the Max Heap property |
| 94 | +void inOrderToMaxHeap(Node* root, vector<int>& nodes, int &index) { |
| 95 | + if (root == NULL) return; // Base case: if node is NULL, return |
| 96 | + |
| 97 | + // Assign the current node's data from the largest remaining value |
| 98 | + root->data = nodes[index--]; // Decrement index after assigning to ensure we take the largest value first |
| 99 | + |
| 100 | + // Recur on the left and right subtrees |
| 101 | + inOrderToMaxHeap(root->left, nodes, index); |
| 102 | + inOrderToMaxHeap(root->right, nodes, index); |
| 103 | +} |
| 104 | + |
| 105 | +// Function to convert the entire BST to Max Heap |
| 106 | +void BST_to_MaxHeap(Node* root) { |
| 107 | + if (root == NULL) return; // Base case: if root is NULL, return |
| 108 | + |
| 109 | + vector<int> nodes; // Vector to store the node values in in-order |
| 110 | + inOrder(root, nodes); // Perform in-order traversal and store node values in 'nodes' |
| 111 | + |
| 112 | + int index = nodes.size() - 1; // Initialize the index to the last element (largest value) |
| 113 | + inOrderToMaxHeap(root, nodes, index); // Assign values from largest to smallest to the tree nodes |
| 114 | +} |
| 115 | + |
| 116 | +// Function to print the tree in preorder (root, left, right) to check the Max Heap property |
| 117 | +void print(Node* root) { |
| 118 | + if (root == NULL) return; // Base case: if node is NULL, return |
| 119 | + |
| 120 | + cout << root->data << " "; // Print the current node's data |
| 121 | + print(root->left); // Recursively print the left subtree |
| 122 | + print(root->right); // Recursively print the right subtree |
| 123 | +} |
| 124 | + |
| 125 | +int main() { |
| 126 | + // Constructing a simple BST |
| 127 | + Node* root = new Node(4); // Root node with value 4 |
| 128 | + root->left = new Node(2); // Left child of root with value 2 |
| 129 | + root->right = new Node(6); // Right child of root with value 6 |
| 130 | + root->left->left = new Node(1); // Left child of node 2 with value 1 |
| 131 | + root->left->right = new Node(3); // Right child of node 2 with value 3 |
| 132 | + root->right->left = new Node(5); // Left child of node 6 with value 5 |
| 133 | + root->right->right = new Node(7); // Right child of node 6 with value 7 |
| 134 | + |
| 135 | + // Convert BST to Max Heap |
| 136 | + BST_to_MaxHeap(root); |
| 137 | + |
| 138 | + // Print the tree in preorder to verify the Max Heap property |
| 139 | + cout << "Preorder of Max Heap: "; |
| 140 | + print(root); // Print the tree's preorder traversal (should satisfy Max Heap property) |
| 141 | + cout << endl; |
| 142 | + |
| 143 | + return 0; |
| 144 | +} |
| 145 | + |
| 146 | +``` |
| 147 | +
|
| 148 | +## Problem Solution Explanation |
| 149 | +
|
| 150 | +Now, let's go through the code and explain each line to understand how the algorithm works. |
| 151 | +
|
| 152 | +```cpp |
| 153 | +#include <iostream> |
| 154 | +#include <vector> |
| 155 | +using namespace std; |
| 156 | +``` |
| 157 | +- Here, we include the necessary header files. `iostream` is used for input and output, and `vector` is used to store the values of the tree nodes in an array. |
| 158 | + |
| 159 | +```cpp |
| 160 | +class Node { |
| 161 | +public: |
| 162 | + int data; // Value of the node |
| 163 | + Node* left; // Left child |
| 164 | + Node* right; // Right child |
| 165 | +``` |
| 166 | +- We define a `Node` class which will represent each node of the tree. Each node holds a `data` value, a pointer to its left child (`left`), and a pointer to its right child (`right`). |
| 167 | +
|
| 168 | +```cpp |
| 169 | + Node(int val) { |
| 170 | + this->data = val; |
| 171 | + this->left = NULL; // Initially, left child is NULL |
| 172 | + this->right = NULL; // Initially, right child is NULL |
| 173 | + } |
| 174 | +}; |
| 175 | +``` |
| 176 | +- The constructor of the `Node` class initializes the node with the given value `val`. Initially, both `left` and `right` pointers are set to `NULL` because it does not have children when first created. |
| 177 | + |
| 178 | +```cpp |
| 179 | +void inOrder(Node* root, vector<int> &nodes) { |
| 180 | + if (root == NULL) return; // Base case: if node is NULL, return |
| 181 | +``` |
| 182 | +- The `inOrder` function performs an **in-order traversal** of the tree. The base case checks if the node is `NULL` and returns if it is. |
| 183 | +
|
| 184 | +```cpp |
| 185 | + inOrder(root->left, nodes); // Recur on the left child |
| 186 | + nodes.push_back(root->data); // Store the current node's data |
| 187 | + inOrder(root->right, nodes); // Recur on the right child |
| 188 | +} |
| 189 | +``` |
| 190 | +- We recursively visit the left subtree, store the current node’s value in the `nodes` vector, and then visit the right subtree. |
| 191 | + |
| 192 | +```cpp |
| 193 | +void inOrderToMaxHeap(Node* root, vector<int>& nodes, int &index) { |
| 194 | + if (root == NULL) return; // Base case: if node is NULL, return |
| 195 | +``` |
| 196 | +- The `inOrderToMaxHeap` function assigns values to the tree nodes, starting from the largest value in the `nodes` vector. |
| 197 | +
|
| 198 | +```cpp |
| 199 | + root->data = nodes[index--]; // Decrement index after assigning to ensure we take the largest value first |
| 200 | +``` |
| 201 | +- We assign the largest value from the `nodes` vector to the current node (`root->data`). After assigning, we decrement the index to ensure the next largest value is assigned next. |
| 202 | + |
| 203 | +```cpp |
| 204 | + inOrderToMaxHeap(root->left, nodes, index); // Recur on the left subtree |
| 205 | + inOrderToMaxHeap(root->right, nodes, index); // Recur on the right subtree |
| 206 | +} |
| 207 | +``` |
| 208 | +- We recursively assign values to the left and right subtrees. |
| 209 | +
|
| 210 | +```cpp |
| 211 | +void BST_to_MaxHeap(Node* root) { |
| 212 | + if (root == NULL) return; // Base case: if root is NULL, return |
| 213 | +``` |
| 214 | +- The `BST_to_MaxHeap` function is the main function that converts the entire BST to a Max Heap. |
| 215 | + |
| 216 | +```cpp |
| 217 | + vector<int> nodes; // Vector to store the node values in in-order |
| 218 | + inOrder(root, nodes); // Perform in-order traversal and store node values in 'nodes' |
| 219 | +``` |
| 220 | +- We create a vector `nodes` to store the node values in sorted order via the `inOrder` function. |
| 221 | +
|
| 222 | +```cpp |
| 223 | + int index = nodes.size() - 1; // Initialize the index to the last element (largest value) |
| 224 | + inOrderToMaxHeap(root, nodes, index); // Assign values from largest to smallest to the tree nodes |
| 225 | +} |
| 226 | +``` |
| 227 | +- We initialize the `index` to the last element of the `nodes` vector (largest value). We then call `inOrderToMaxHeap` to assign values to the tree nodes in a way that maintains the Max Heap property. |
| 228 | + |
| 229 | +```cpp |
| 230 | +void print(Node* root) { |
| 231 | + if (root == NULL) return; // Base case: if node is NULL, return |
| 232 | + cout << root->data << " "; // Print the current node's data |
| 233 | + print(root->left); // Recursively print the left subtree |
| 234 | + print(root->right); // Recursively print the right subtree |
| 235 | +} |
| 236 | +``` |
| 237 | +- The `print` function is used to print the tree in **preorder** (root, left, right). This helps verify if the tree satisfies the Max Heap property. |
| 238 | +
|
| 239 | +```cpp |
| 240 | +int main() { |
| 241 | + Node* root = new Node(4); // Root node with value 4 |
| 242 | + root->left = new Node(2); // Left child of root with value 2 |
| 243 | + root->right = new Node(6); // Right child of root with value 6 |
| 244 | + root->left->left = new Node(1); // Left child of node 2 with value 1 |
| 245 | + root->left->right = new Node(3); // Right child of node 2 with value 3 |
| 246 | + root->right->left = new Node(5); // Left child of node 6 with value 5 |
| 247 | + root->right->right = new Node(7); // Right child of node 6 with value 7 |
| 248 | +
|
| 249 | + BST_to_MaxHeap(root); // Convert BST to Max Heap |
| 250 | +
|
| 251 | + cout << "Preorder of Max Heap: "; |
| 252 | + print(root); // Print the tree's preorder traversal (should satisfy Max Heap property) |
| 253 | + cout << endl; |
| 254 | +
|
| 255 | + return 0; |
| 256 | +} |
| 257 | +``` |
| 258 | +- In the `main` function, we construct a simple BST and convert it to a Max Heap. We then print the preorder traversal to verify the Max Heap property. |
| 259 | + |
| 260 | +### Step 3: Examples and Explanation |
| 261 | + |
| 262 | +For the example BST: |
| 263 | +``` |
| 264 | + 4 |
| 265 | + / \ |
| 266 | + 2 6 |
| 267 | + / \ / \ |
| 268 | + 1 3 5 7 |
| 269 | +``` |
| 270 | +After performing in-order traversal, we get: `[1, 2, 3, 4, 5, 6, 7]`. We then assign values to the tree nodes from largest to smallest, starting with the root: |
| 271 | +``` |
| 272 | + 7 |
| 273 | + / \ |
| 274 | + 6 5 |
| 275 | + / \ / \ |
| 276 | + 1 3 2 4 |
| 277 | +``` |
| 278 | +Preorder traversal of the Max Heap: `7 6 1 3 2 4 5`. |
| 279 | + |
| 280 | +### Step 4: Time and Space Complexity |
| 281 | + |
| 282 | +**Time Complexity**: |
| 283 | +- In-order traversal takes **O(n)** time, where `n` is the number of nodes in the tree. |
| 284 | +- The `inOrderToMaxHeap` function also takes **O(n)** time as we visit each node once. |
| 285 | +Thus, the overall time complexity is **O(n)**. |
| 286 | + |
| 287 | +**Space Complexity**: |
| 288 | +- The space complexity is |
| 289 | + |
| 290 | + **O(n)** due to the storage required for the `nodes` vector. |
| 291 | + |
| 292 | +This is an efficient solution that correctly converts a BST to a Max Heap. |
0 commit comments