Merge2BST InOrder
#include <bits/stdc++.h> // Includes common standard libraries (iostream, vector, utility for pair, etc.)#include "BST.h" // Assumed to contain Node class, takeinput, levelOrderTraversal
using namespace std; // Use the standard namespace
// Note: The Node class, takeinput, and levelOrderTraversal// are assumed to be defined in "BST.h"./*class Node {public: int data; Node* left; Node* right; Node(int data) { // Constructor for Node this->data = data; this->left = NULL; this->right = NULL; }};
void takeinput(Node* &root) { ... }void levelOrderTraversal(Node* root) { ... }*/
// Helper function: Performs an in-order traversal of a BST// and stores all node data into the 'ans' vector in sorted order.// Time Complexity: O(N), where N is the number of nodes in the tree.// Space Complexity: O(H) for recursion stack, where H is the tree's height.void inOrder(Node* root, vector<int>& ans) { if(root == NULL) { return; } inOrder(root->left, ans); // Traverse left ans.push_back(root->data); // Process current node inOrder(root->right, ans); // Traverse right}
// Helper function: Merges two sorted arrays (arr1 and arr2) into a single sorted array.// This is a standard merge step from merge sort.// Time Complexity: O(N1 + N2), where N1 and N2 are sizes of arr1 and arr2.// Space Complexity: O(N1 + N2) for the 'solution' vector.vector<int> mergeArrays(vector<int> arr1, vector<int> arr2) { // Handle edge cases where one or both arrays are empty. if(arr1.empty() && arr2.empty()) return {}; if(arr1.empty()) return arr2; if(arr2.empty()) return arr1;
int i = 0, j = 0; vector<int> solution; // To store the merged sorted elements
// Compare elements from both arrays and add the smaller one to 'solution'. while(i < arr1.size() && j < arr2.size()) { if(arr1[i] < arr2[j]) { solution.push_back(arr1[i++]); } else { solution.push_back(arr2[j++]); } }
// Add any remaining elements from arr1 (if arr2 was exhausted). while(i < arr1.size()) { solution.push_back(arr1[i++]); }
// Add any remaining elements from arr2 (if arr1 was exhausted). while(j < arr2.size()) { solution.push_back(arr2[j++]); }
return solution;}
// Helper function: Builds a balanced BST from a sorted array.// This is crucial for ensuring the merged tree is balanced.// Time Complexity: O(N), where N is the number of elements in 'arr'.// Space Complexity: O(log N) for recursion stack due to balanced construction.Node* createBST(vector<int> &arr, int start, int end) { // Base case: If subarray is empty, return NULL. if(start > end) { return NULL; }
// Find the middle element; it becomes the root of the current subtree. int mid = start + (end - start) / 2; Node* temp = new Node(arr[mid]);
// Recursively build the left subtree from the left half of the array. temp->left = createBST(arr, start, mid - 1); // Recursively build the right subtree from the right half of the array. temp->right = createBST(arr, mid + 1, end);
return temp; // Return the root of the constructed subtree.}
// Main function to merge two BSTs into a single balanced BST.// Time Complexity: O(N1 + N2), where N1 and N2 are nodes in root1 and root2.// Space Complexity: O(N1 + N2) for storing arrays.Node* MergeBST(Node* root1, Node* root2) { // Step 1: Extract sorted elements from both BSTs using in-order traversal. vector<int> arr1; vector<int> arr2; inOrder(root1, arr1); inOrder(root2, arr2);
// Step 2: Merge the two sorted arrays into a single sorted array. vector<int> resultArray = mergeArrays(arr1, arr2);
// Step 3: Build a new balanced BST from the combined sorted array. Node* answer = createBST(resultArray, 0, resultArray.size() - 1);
// Optional: Print level order traversal of the merged BST from within this function. // This helps in verifying the output immediately after creation. cout << endl << "Level Order Traversal of merged BST (inside MergeBST function) : " << endl; levelOrderTraversal(answer);
return answer; // Return the root of the newly merged and balanced BST.}
int main() { Node* root1 = NULL; // Initialize root of the first BST Node* root2 = NULL; // Initialize root of the second BST
cout << "Enter data to create BST 1 (e.g., 50 40 60 70 -1) : "; takeinput(root1); // Build BST 1
cout << "Enter data to create BST 2 (e.g., 55 45 35 65 47 -1) : "; takeinput(root2); // Build BST 2
cout << endl << "Level Order Traversal of BST 1 : " << endl; levelOrderTraversal(root1); // Print BST 1
cout << endl << "Level Order Traversal of BST 2 : " << endl; levelOrderTraversal(root2); // Print BST 2
// Call the MergeBST function to get the merged and balanced BST. Node* result = MergeBST(root1, root2);
// Print the level order traversal of the final merged BST from main. // This confirms the returned 'result' pointer is correct. cout << endl << "Level Order Traversal of final merged BST (from main) : " << endl; levelOrderTraversal(result);
return 0;}
/*Example Inputs:BST 1: 50 40 60 70 -1BST 2: 55 45 35 65 47 -1
BST 1 (In-order): 40, 50, 60, 70BST 2 (In-order): 35, 45, 47, 55, 65
Merged Sorted Array: 35, 40, 45, 47, 50, 55, 60, 65, 70
Expected Merged and Balanced BST (Level Order Traversal):(Middle element of merged array is 50, so it's the root) 50 / \ 40 60 / \ / \ 35 45 55 70 / / 47 65
Output of Level Order Traversal:50 40 60 35 45 55 70 47 65*/
1. Binary Search Tree (BST) Recap
- A Binary Search Tree (BST) organizes nodes such that left children are smaller and right children are larger.
- In-order Traversal: Visiting nodes in
Left -> Root -> Right
order yields elements in strictly ascending (sorted) order. - Balanced BST: A BST where the height is minimized (
O(log N)
), ensuring efficient operations.
2. Core Idea for Merging Two BSTs
The most common and efficient strategy to merge two BSTs into a single balanced BST involves three main steps:
- Convert to Sorted Arrays: Extract all elements from both BSTs into separate sorted arrays (or vectors) using in-order traversal.
- Merge Sorted Arrays: Combine these two sorted arrays into a single, larger sorted array.
- Build Balanced BST: Construct a new, perfectly balanced BST from this combined sorted array.
3. Supporting Components (Briefly)
Node
class: Defines the structure of a BST node (data
,left
,right
).takeinput
,levelOrderTraversal
: Functions (assumed inBST.h
) to build and visualize the BSTs.
4. inOrder(Node* root, vector<int>& ans)
Function
- Purpose: Helper function to perform an in-order traversal of a BST and collect all node data into a
vector<int>
in sorted order. - Logic: Standard recursive in-order traversal (
Left -> Root -> Right
).- Base case: If
root
isNULL
, return. - Recursively traverse
root->left
. - Add
root->data
to theans
vector. - Recursively traverse
root->right
.
- Base case: If
5. mergeArrays(vector<int> arr1, vector<int> arr2)
Function
- Purpose: Merges two already sorted input vectors (
arr1
andarr2
) into a single, sortedvector<int>
. - Logic: Uses the classic two-pointer technique, similar to the merge step in Merge Sort.
- Initialize two pointers,
i
forarr1
andj
forarr2
, both starting at 0. - Initialize an empty
solution
vector. - Loop
while (i < arr1.size() && j < arr2.size())
:- Compare
arr1[i]
andarr2[j]
. - Add the smaller element to
solution
and advance its respective pointer.
- Compare
- After the main loop, one of the arrays might still have remaining elements. Add all remaining elements from
arr1
(if any) tosolution
. - Add all remaining elements from
arr2
(if any) tosolution
. - Return the
solution
vector.
- Initialize two pointers,
6. createBST(vector<int> &arr, int start, int end)
Function
- Purpose: Recursively builds a perfectly balanced BST from a given sorted array (or subarray).
- Logic:
- Base Case: If
start > end
, the subarray is empty; returnNULL
. - Find Middle: Calculate
mid = start + (end - start) / 2
. Thismid
element will be the root of the current subtree. - Create Node: Create a new
Node
witharr[mid]
. - Build Left Subtree: Recursively call
createBST
for the left subarray (start
tomid-1
). - Build Right Subtree: Recursively call
createBST
for the right subarray (mid+1
toend
). - Return the newly created root node.
- Base Case: If
7. MergeBST(Node* root1, Node* root2)
Function
- Purpose: The main function that orchestrates the merging of the two BSTs.
- Logic Flow:
- Extract Elements:
- Call
inOrder(root1, arr1)
to get sorted elements from the first BST. - Call
inOrder(root2, arr2)
to get sorted elements from the second BST.
- Call
- Merge Sorted Lists:
- Call
mergeArrays(arr1, arr2)
to combine the two sorted lists into oneresultArray
.
- Call
- Build Final BST:
- Call
createBST(resultArray, 0, resultArray.size()-1)
to construct a new, balanced BST from theresultArray
.
- Call
- Print & Return:
- (Optional, but present in code) Print the level order traversal of the newly formed merged BST for verification.
- Return the root of the
answer
(the merged BST).
- Extract Elements:
8. Complexity Analysis
-
Let
N1
be the number of nodes inBST1
andN2
be the number of nodes inBST2
. -
N = N1 + N2
is the total number of nodes in the merged BST. -
Time Complexity:
O(N1 + N2)
which isO(N)
.inOrder
forBST1
:O(N1)
.inOrder
forBST2
:O(N2)
.mergeArrays
:O(N1 + N2) = O(N)
.createBST
:O(N1 + N2) = O(N)
.- Total:
O(N)
.
-
Space Complexity:
O(N)
O(N1)
forarr1
,O(N2)
forarr2
.O(N1 + N2) = O(N)
forresultArray
.O(H1)
+O(H2)
forinOrder
recursion stacks (maxO(N1)
+O(N2)
).O(log N)
forcreateBST
recursion stack (due to balanced construction).- Total:
O(N)
due to vector storage.