Validate BST
#include <bits/stdc++.h> // Includes common standard libraries (iostream, queue, limits for INT_MIN/INT_MAX)#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" for this snippet.// For completeness, they are usually:/*class Node {public: int data; Node* left; Node* right; Node(int data) { this->data = data; this->left = NULL; this->right = NULL; }};
Node* insertIntoBST(Node* root, int data) { ... }void takeinput(Node* &root) { ... }void levelOrderTraversal(Node* root) { ... }*/
// Function to validate if a given Binary Tree is a Binary Search Tree (BST).// This recursive function passes down a valid range [min, max] for node values.// Time Complexity: O(N) - visits each node once.// Space Complexity: O(H) - recursion stack space, where H is tree height.bool ValidateBST(Node* root, int min, int max) { // Base Case: An empty tree (or subtree) is always a valid BST. if(root == NULL) { return true; }
// Check if the current node's data is within the allowed range [min, max]. // If it violates the range, it's not a BST. if(root->data >= min && root->data <= max) { // Recursively validate the left subtree: // Its new max bound becomes root->data (all left nodes must be <= root->data). // Its min bound remains the same. bool leftIsValid = ValidateBST(root->left, min, root->data);
// Recursively validate the right subtree: // Its new min bound becomes root->data (all right nodes must be >= root->data). // Its max bound remains the same. bool rightIsValid = ValidateBST(root->right, root->data, max);
// The current subtree is a valid BST ONLY if both its left and right subtrees are valid. return (leftIsValid && rightIsValid); }
// If the current node's data violates the min/max range, it's not a BST. return false;}
int main() { Node* root = NULL; // Initialize root of the binary tree
cout << "Enter data to create BST (use -1 for NULL, this function builds a BST by default if BST.h is from previous example): "; // This takeinput function likely inserts data according to BST rules, // so the resulting tree should already be a BST if inputs are unique. // For general BST validation, you'd feed a potentially invalid binary tree. takeinput(root);
cout << endl << "Level Order Traversal of the created tree : " << endl; levelOrderTraversal(root); // Print the tree structure
// Validate the created tree, starting with the broadest possible range for the root. // INT_MIN and INT_MAX are from <limits> header. if(ValidateBST(root, INT_MIN, INT_MAX)) { cout << "YES ! It is a Binary Search Tree." << endl; } else { cout << "NO ! It is not a Binary Search Tree." << endl; }
return 0;}
/*Example INPUT for tree creation:(Assuming BST.h's takeinput builds a standard BST)1. Valid BST Input: 50 20 70 10 30 60 80 -1 Output: YES ! It is a Binary Search Tree.
2. Invalid BST Input (This requires modifying buildTree/takeinput in BST.h to build an arbitrary binary tree, not strictly a BST. For example, if you manually create a tree like: 50 / \ 70 20 (i.e., 70 on left of 50, 20 on right of 50) Then ValidateBST(root, INT_MIN, INT_MAX) would return false. The provided `takeinput` builds a valid BST, so for `NO` output, one would need a custom tree builder that doesn't enforce BST rules during creation. However, if you input something like: `10 5 15 12 18 -1` Tree: 10 / \ 5 15 / \ 12 18 This is a valid BST.
If you had a non-BST construction and built: 10 / \ 20 5 ValidateBST(root, INT_MIN, INT_MAX) for this would be: - ValidateBST(10, INT_MIN, INT_MAX) - 10 is in range. - Call left: ValidateBST(20, INT_MIN, 10) -> 20 is NOT <= 10. Returns false. - Result: false Output: NO ! It is not a Binary Search Tree.*/
1. Binary Search Tree (BST) Properties Recap
- A Binary Search Tree (BST) is defined by its ordering property:
- For every node, all values in its left subtree must be less than its own data.
- For every node, all values in its right subtree must be greater than its own data.
- Both left and right subtrees must also recursively be BSTs.
- Crucial Point: It’s not just about immediate children; the property applies to all descendants in a subtree.
2. Supporting Components (Briefly)
Node
class: Defines the structure of a binary tree node (data
,left
,right
).insertIntoBST
,takeinput
,levelOrderTraversal
: These functions (assumed to be inBST.h
) are used to create and display the binary tree which will then be validated. Note thattakeinput
forBST.h
would typically build a valid BST. For validation, one might pass an arbitrary binary tree (not necessarily built viainsertIntoBST
). However, this code usesinsertIntoBST
for creation, implying it’s testing if the insertion process itself yields a BST. If you want to test any binary tree,takeinput
should be generic, not BST-specific.
3. ValidateBST(Node* root, int min, int max)
Function (Recursive Validation)
-
Purpose: Determines if a given binary tree (or subtree) adheres to all BST properties.
-
Core Idea: The most robust way to validate a BST is to pass down a valid range (
min
andmax
boundaries) that each node’s data must fall within. As we recurse, these bounds are tightened. -
Parameters:
Node* root
: The current node being checked.int min
: The minimum permissible value for any node in the current subtree. Values less than or equal tomin
are invalid.int max
: The maximum permissible value for any node in the current subtree. Values greater than or equal tomax
are invalid.
-
Logic Flow:
- Base Case:
if (root == NULL)
: An empty tree (or subtree) is always considered a valid BST. Returntrue
.
- Current Node Check:
if (root->data >= min && root->data <= max)
:- Check if the
data
of the currentroot
node lies within the allowedmin
andmax
range inherited from its ancestors. - If it violates this, the entire tree is not a BST. The
else
part (returningfalse
) handles this.
- Check if the
- Recursive Calls (If current node is valid):
bool left = ValidateBST(root->left, min, root->data);
- Recursively validate the left subtree.
- The
min
bound for the left child remains the same as its parent’smin
. - The
max
bound for the left child becomesroot->data
. This is crucial: all nodes in the left subtree must be strictly less than the currentroot->data
. (Note: The code uses<=
which means duplicates would be allowed on the left, but usually BSTs have strict<
for left and>
for right or a specific policy for equals. GiveninsertIntoBST
puts duplicates on left,<=
is consistent).
bool right = ValidateBST(root->right, root->data, max);
- Recursively validate the right subtree.
- The
min
bound for the right child becomesroot->data
. This is crucial: all nodes in the right subtree must be strictly greater than the currentroot->data
. - The
max
bound for the right child remains the same as its parent’smax
.
- Combine Results:
return (left && right);
- The current subtree is a valid BST only if both its left and right subtrees are also valid BSTs.
- Invalid Node:
return false;
: This line is reached ifroot->data
violates themin
/max
bounds, meaning the BST property is broken at this node.
- Base Case:
-
Initial Call in
main
:ValidateBST(root, INT_MIN, INT_MAX)
: The entire tree starts with the broadest possible range.INT_MIN
andINT_MAX
(from<limits>
) are used as initial unbounded limits.
4. Complexity Analysis for Validation
- Time Complexity:
O(N)
- Every node in the binary tree is visited exactly once.
- Space Complexity:
O(H)
- Due to the recursion call stack, where
H
is the height of the tree. - Worst Case (Skewed Tree):
H = N
, leading toO(N)
space. - Best Case (Balanced Tree):
H = log N
, leading toO(log N)
space.
- Due to the recursion call stack, where