Normal BST to Balanced BST
#include <bits/stdc++.h> // Includes common standard libraries (iostream, vector, etc.)#include "BST.h" // Assumed to contain Node class, insertIntoBST, takeinput, levelOrderTraversal
using namespace std; // Use the standard namespace
// Note: The Node class, insertIntoBST, takeinput, and levelOrderTraversal// are assumed to be defined in "BST.h"./*class Node {public: int data; Node* left; Node* right; Node(int data) { ... }};
Node* insertIntoBST(Node* root, int data) { ... }void takeinput(Node* &root) { ... }void levelOrderTraversal(Node* root) { ... }*/
// Helper function: Performs an in-order traversal of the BST// and stores all node data into the 'ans' vector in sorted order.// This is the first step to get data in a linear, sorted format.// Time Complexity: O(N)// Space Complexity: O(H) for recursion stackvoid inOrder(Node* root, vector<int>& ans) { // Base case: If current node is NULL, return. if(root == NULL) { return; }
// Recursively traverse the left subtree. inOrder(root->left, ans); // Process current node: add its data to the vector. ans.push_back(root->data); // Recursively traverse the right subtree. inOrder(root->right, ans);}
// Helper function: Builds a balanced BST from a sorted array.// This is the second step to construct the new balanced tree.// Time Complexity: O(N) (each element processed once)// Space Complexity: O(log N) for recursion stack (due to balanced construction)Node* balanceBST(vector<int>& arr, int start, int end) { // Base case: If the subarray is empty (start index > end index), return NULL. if(start > end) { // Equivalent to end-start < 0 return NULL; }
// Find the middle element. This will be the root of the current subtree. int mid = start + (end - start) / 2; // Create a new node for the root of this subtree. Node* temp = new Node(arr[mid]);
// Recursively build the left subtree from the left half of the array. temp->left = balanceBST(arr, start, mid - 1); // Recursively build the right subtree from the right half of the array. temp->right = balanceBST(arr, mid + 1, end);
// Return the root of the newly constructed balanced subtree. return temp;}
// Main function to convert a normal BST to a balanced BST.// This function orchestrates the two helper functions.// Time Complexity: O(N)// Space Complexity: O(N)Node* NormalToBalance(Node* &root) { // 'root' is passed by reference, but not directly reassigned in this function // If the original BST is empty, the balanced one is also empty. if(root == NULL) { return NULL; }
// Step 1: Perform in-order traversal to get all node data in a sorted vector. vector<int> arr; inOrder(root, arr);
// Step 2: Build a new balanced BST from the sorted vector. // '0' is the starting index and 'arr.size()-1' is the ending index of the vector. Node* newBSTroot = balanceBST(arr, 0, arr.size() - 1);
// Return the root of the newly created balanced BST. return newBSTroot;}
int main() { Node* root = NULL; // Initialize root of the original BST
cout << "Enter data to create BST : "; takeinput(root); // Build the original BST (can be unbalanced)
cout << endl << "Level Order Traversal of Original BST : " << endl; levelOrderTraversal(root); // Print the original BST
// Convert the original BST to a new balanced BST. // 'newRoot' will point to the root of the balanced tree. Node* newRoot = NormalToBalance(root);
cout << endl << "Level Order Traversal of Balanced BST : " << endl; levelOrderTraversal(newRoot); // Print the newly created balanced BST
// Note: The original 'root' still points to the old (potentially unbalanced) tree. // If you need to clean up the old tree, you would add logic here.
return 0;}
/*Example Input for tree creation (can lead to unbalanced trees):10 8 12 5 15 2 18 -1Original Tree: 10 / \ 8 12 / \ 5 15 / \ 2 18
In-order sorted elements: 2, 5, 8, 10, 12, 15, 18
Balanced BST construction from sorted array:- mid = 10 -> Root is 10- left of 10: [2, 5, 8] -> mid = 5 -> Left child of 10 is 5 - left of 5: [2] -> mid = 2 -> Left child of 5 is 2 - right of 5: [8] -> mid = 8 -> Right child of 5 is 8- right of 10: [12, 15, 18] -> mid = 15 -> Right child of 10 is 15 - left of 15: [12] -> mid = 12 -> Left child of 15 is 12 - right of 15: [18] -> mid = 18 -> Right child of 15 is 18
Expected Balanced Tree (Level Order): 10 / \ 5 15 / \ / \ 2 8 12 18
Output of Level Order Traversal of Balanced BST:10 5 15 2 8 12 18*/
1. Binary Search Tree (BST) Recap
- A Binary Search Tree (BST) organizes nodes such that left children are smaller and right children are larger.
- Balanced BST: A balanced BST (like an AVL tree or Red-Black tree) ensures that its height remains
O(log N)
whereN
is the number of nodes. This prevents degenerate cases (like a skewed tree) where operations (search, insert, delete) could takeO(N)
time. Balancing aims to keep these operations efficient atO(log N)
.
2. Core Idea for Balancing a BST
The most common strategy to balance an arbitrary BST is:
- Perform an In-order traversal of the existing BST to get all its elements in sorted order.
- Build a new, balanced BST from this sorted list of elements.
3. Supporting Components (Briefly)
Node
class: Defines the structure of a BST node (data
,left
,right
).insertIntoBST
,takeinput
,levelOrderTraversal
: Functions (assumed inBST.h
) to build and visualize the original BST.
4. inOrder(Node* root, vector<int>& ans)
Function
- Purpose: This is a helper function that performs a standard in-order traversal on the BST to collect all node data into a
vector<int>
. - Logic: Standard recursive in-order:
left -> root -> right
.- Base Case: If
root
isNULL
, return. - Traverse Left: Recursively call
inOrder
onroot->left
. - Process Node: Add
root->data
to theans
vector. - Traverse Right: Recursively call
inOrder
onroot->right
.
- Base Case: If
- Result:
ans
vector contains all BST node values in sorted (ascending) order.
5. balanceBST(vector<int>& arr, int start, int end)
Function
- Purpose: Recursively constructs a perfectly balanced BST from a given sorted array (or subarray).
- Core Idea: For a sorted array, the middle element always becomes the root of the current (sub)tree to ensure balance. Elements to its left form the left subtree, and elements to its right form the right subtree.
- Logic:
- Base Case:
if(start > end)
(orend-start < 0
as used in code): This means the current subarray is empty. ReturnNULL
. - Find Middle:
int mid = start + (end - start) / 2;
Calculates the middle index. Thismid
element will be the root of the current subtree. - Create Root Node:
Node* temp = new Node(arr[mid]);
Creates a new node with the middle element’s value. - Build Left Subtree:
temp->left = balanceBST(arr, start, mid - 1);
Recursively calls itself to build the left subtree using the elements fromstart
tomid-1
. - Build Right Subtree:
temp->right = balanceBST(arr, mid + 1, end);
Recursively calls itself to build the right subtree using the elements frommid+1
toend
. - Return Root: Return
temp
, which is the root of the newly formed balanced subtree.
- Base Case:
6. NormalToBalance(Node* &root)
Function
- Purpose: Orchestrates the entire process of converting an unbalanced BST to a balanced one.
- Logic Flow:
- Handle Empty Input: If the initial
root
isNULL
, returnNULL
. - Collect Sorted Data: Create an empty
vector<int> arr;
and callinOrder(root, arr);
. This populatesarr
with all node data in sorted order. - Build Balanced BST: Call
balanceBST(arr, 0, arr.size() - 1);
passing the full sorted array and its bounds. This function will return the root of the newly constructed balanced BST. - Return New Root: Return the root of the balanced BST. (Note: The
root
parameter here is passed by reference, but its value is not directly modified in this function;main
receives the new root asnewRoot
. The&
is not strictly necessary for this specific usage, but generally indicates an intent to modifyroot
.)
- Handle Empty Input: If the initial
7. Complexity Analysis
- Time Complexity:
O(N)
O(N)
for theinOrder
traversal to collect allN
node data.O(N)
forbalanceBST
to createN
new nodes and set up pointers (each node is visited and created once).- Total:
O(N)
.
- Space Complexity:
O(N)
O(N)
for storing allN
integer data values in thevector<int> arr
.O(H)
for the recursion stack ofinOrder
traversal (maxO(N)
for skewed).O(H_new)
for the recursion stack ofbalanceBST
(maxO(log N)
for a perfectly balanced tree, but in worst case of input array/recursion depth can beO(N)
if not handled carefully). In this balanced construction,H_new
isO(log N)
.- Total: Dominated by the vector storage, so
O(N)
.