- Data Structure
- Networking
- RDBMS
- Operating System
- Java
- MS Excel
- iOS
- HTML
- CSS
- Android
- Python
- C Programming
- C++
- C#
- MongoDB
- MySQL
- Javascript
- PHP
- Physics
- Chemistry
- Biology
- Mathematics
- English
- Economics
- Psychology
- Social Studies
- Fashion Studies
- Legal Studies
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Find median of BST in O(n) time and O(1) space in C++
Concept
With respect of a given Binary Search Tree(BST), our task is to determine median of it.
For even no. of nodes, median = ((n/2th node + (n+1)/2th node) /2 For odd no. of nodes, median = (n+1)/2th node.
For given BST(with odd no. of nodes) is −
7 / \ 4 9 / \ / \ 2 5 8 10
Inorder of Given BST will be : 2, 4, 5, 7, 8, 9, 10 So, here median will 7.
For given BST(with even no. of nodes) is −
7 / \ 4 9 / \ / 2 5 8
Inorder of Given BST will be − 2, 4, 5, 7, 8, 9
So, here median will (5+7)/2 = 6.
Method
For determining the median, we need to determine the inorder of the BST because its inorder will be in sorted order and then determine the median. Here, the concept is based on K’th smallest element in BST using O(1) extra Space. Now, the task is very simple if we are permitted to implement extra space but Inorder traversal implementing recursion and stack both uses space which is not permitted here.
As a result of this, the solution is to perform Morris Inorder Traversal because it doesn’t require any extra space.
Morris Inorder Traversal is explained in following way −
- We initialize current as root
- While current is not NULL
If the current does not have left child
- Print current’s data
- Move to the right, i.e., current = current->right
Else
- Construct current as the right child of the rightmost node in current's left subtree
- Move to this left child, i.e., current = current->left
Final implementation is discussed in following way −
We count the no. of nodes in the given BST implementing Morris Inorder Traversal.
After that perform Morris Inorder Traversal one more time by counting nodes and by verifying if count is equal to the median point.
For considering even no. of nodes an extra pointer pointing to the previous node is implemented.
Example
/* C++ program to find the median of BST in O(n) time and O(1) space*/ #include<bits/stdc++.h> using namespace std; /* Implements a binary search tree Node1 which has data, pointer to left child and a pointer to right child */ struct Node1{ int data1; struct Node1* left1, *right1; }; //Shows a utility function to create a new BST node struct Node1 *newNode(int item1){ struct Node1 *temp1 = new Node1; temp1->data1 = item1; temp1->left1 = temp1->right1 = NULL; return temp1; } /* Shows a utility function to insert a new node with given key in BST */ struct Node1* insert(struct Node1* node1, int key1){ /* It has been seen that if the tree is empty, return a new node */ if (node1 == NULL) return newNode(key1); /* Else, recur down the tree */ if (key1 < node1->data1) node1->left1 = insert(node1->left1, key1); else if (key1 > node1->data1) node1->right1 = insert(node1->right1, key1); /* return the (unchanged) node pointer */ return node1; } /* Shows function to count nodes in a binary search tree using Morris Inorder traversal*/ int counNodes(struct Node1 *root1){ struct Node1 *current1, *pre1; // Used to initialise count of nodes as 0 int count1 = 0; if (root1 == NULL) return count1; current1 = root1; while (current1 != NULL){ if (current1->left1 == NULL){ // Now count node if its left is NULL count1++; // Go to its right current1 = current1->right1; } else { /* Determine the inorder predecessor of current */ pre1 = current1->left1; while (pre1->right1 != NULL && pre1->right1 != current1) pre1 = pre1->right1; /* Construct current1 as right child of its inorder predecessor */ if(pre1->right1 == NULL){ pre1->right1 = current1; current1 = current1->left1; } /* we have to revert the changes made in if part to restore the original tree i.e., fix the right child of predecssor */ else { pre1->right1 = NULL; // Now increment count if the current // node is to be visited count1++; current1 = current1->right1; } /* End of if condition pre1->right1 == NULL */ } /* End of if condition current1->left1 == NULL*/ } /* End of while */ return count1; } /* Shows function to find median in O(n) time and O(1) space using Morris Inorder traversal*/ int findMedian(struct Node1 *root1){ if (root1 == NULL) return 0; int count1 = counNodes(root1); int currCount1 = 0; struct Node1 *current1 = root1, *pre1, *prev1; while (current1 != NULL){ if (current1->left1 == NULL){ // Now count current node currCount1++; // Verify if current node is the median // Odd case if (count1 % 2 != 0 && currCount1 == (count1+1)/2) return prev1->data1; // Even case else if (count1 % 2 == 0 && currCount1 == (count1/2)+1) return (prev1->data1 + current1->data1)/2; // Now update prev1 for even no. of nodes prev1 = current1; //Go to the right current1 = current1->right1; } else { /* determine the inorder predecessor of current1 */ pre1 = current1->left1; while (pre1->right1 != NULL && pre1->right1 != current1) pre1 = pre1->right1; /* Construct current1 as right child of its inorder predecessor */ if (pre1->right1 == NULL){ pre1->right1 = current1; current1 = current1->left1; } /* We have to revert the changes made in if part to restore the original tree i.e., fix the right child of predecssor */ else { pre1->right1 = NULL; prev1 = pre1; // Now count current node currCount1++; // Verify if the current node is the median if (count1 % 2 != 0 && currCount1 == (count1+1)/2 ) return current1->data1; else if (count1%2==0 && currCount1 == (count1/2)+1) return (prev1->data1+current1->data1)/2; // Now update prev1 node for the case of even // no. of nodes prev1 = current1; current1 = current1->right1; } /* End of if condition pre1->right1 == NULL */ } /* End of if condition current1->left1 == NULL*/ } /* End of while */ } /* Driver program to test above functions*/ int main(){ /* Let us create following BST 7 / \ 4 9 / \ / \ 2 5 8 10 */ struct Node1 *root1 = NULL; root1 = insert(root1, 7); insert(root1, 4); insert(root1, 2); insert(root1, 5); insert(root1, 9); insert(root1, 8); insert(root1, 10); cout << "\nMedian of BST is(for odd no. of nodes) "<< findMedian(root1) <<endl; /* Let us create following BST 7 / \ 4 9 / \ / 2 5 8 */ struct Node1 *root2 = NULL; root2 = insert(root2, 7); insert(root2, 4); insert(root2, 2); insert(root2, 5); insert(root2, 9); insert(root2, 8); cout << "\nMedian of BST is(for even no. of nodes) " << findMedian(root2); return 0; }
Output
Median of BST is(for odd no. of nodes) 7 Median of BST is(for even no. of nodes) 6