How to check if a tree is binary search tree (BST)

How to validate binary search tree


Category: Data Structure And Algorithms Tags: C#

How to check if a tree is binary search tree - Code Files

Problem Statement

    Write a method to validate if given binary tree is a binary search tree or not.

Solution

    All binary search trees are binary trees but not all binary trees are binary search trees(BSTs). A binary tree can have max of two children at each node. When left child of a node (and all nodes in left subtree) is smaller or equals to root and right child of node (and all nodes in right subtree) is grater then it is called a Binary Search Tree. More details on BST can be found here.

Method 1: Keep min and max value for each node

    We know a left child and all nodes in left subtree should be less than or equal to its parent and exactly opposite for right node and all nodes in right subtree satisfies condition for BST. We will start with keeping range of integer’s min and max values for root and update them for each level accordingly. Look at the code below:

    static bool IsBinarySearchTreeTraversal(Node root, int minValue, int maxValue)
    {
        if (root == null)
        {
            return true;
        }

        // Check BST condition on each node
        // Initial min is int.max and max is int.max
        // For left node, max should not be more than root's value and for right node, min should be grater than root's value
        if (root.Key > minValue && root.Key < maxValue)
        {
            // Adding 1 in max for root's key to satisfy duplicates when root and its left can be same value
            return IsBinarySearchTreeTraversal(root.Left, minValue, root.Key + 1) && IsBinarySearchTreeTraversal(root.Right, root.Key, maxValue);
        }

        return false;
    }

In above code we are checking min and max range for each node if satisfied then we get into next level where for left node max is updated to (root’s key + 1) and for right node min is updated to (root’s key). So when recursive call gets into next level it checks updated min and max values for nodes. Lets run the code.

    static void Main(string[] args)
    {
        Node root = new Node(20);
        root.Left = new Node(15);
        root.Right = new Node(25);
        root.Left.Left = new Node(10);
        root.Left.Right = new Node(18);
        root.Right.Right = new Node(30);

        /*
            
                20
                /\
              15  25
             /  \   \
            10  18   30
        */

        Console.WriteLine($"IsBinarySearchTree (TraversalAlgo): {IsBinarySearchTreeTraversal(root, int.MinValue, int.MaxValue)}");
    }

Output

IsBinarySearchTree (TraversalAlgo): True

Method 2: Use Inorder traversal and additional pointer to keep track of last item

We know how Inorder traversal works, firstly it goes to left most node of a tree and from there it traverse back to parent and then look for right node. So the traversal on a node should be as shown in picture below.

Inorder traversal
Fig 1: Inorder traversal

 

So when control starts at Left we use additional pointer to store it. When control goes to Root we compare Root with Left (stored in additional pointer), we also set pointer to Root. At the end we compare Right with Root (stored in additional pointer). So flow checks if Root > Left and Right > Root, if yes then returns true. Look at the code below for better understanding.

    // Need extra pointer to keep previous value
    static Node prev;
    static bool IsBinarySearchTreeInOrder(Node current)
    {
        if (current == null)
        {
            return true;
        }

        if (IsBinarySearchTreeInOrder(current.Left))
        {
            if (prev != null)
            {
                // Root's left should be smaller and right should be greater
                // Traversal of nodes in InOrder is left, then root than right
                //     root
                //     / \
                //  Left  Right
                // So when prev is left and current is root then condition should satisfy current>prev
                // When prev is root and current is right then condition should satisfy current>prev
                // Same in both cases
                if (current.Key < prev.Key)
                {
                    return false;
                }
            }

            prev = current;

            return IsBinarySearchTreeInOrder(current.Right);
        }

        return false;
    }

Let’s run this code.

    static void Main(string[] args)
    {
prev = null; var root = new Node(20); root.Left = new Node(20); root.Right = new Node(25); /* 20 /\ 20 25 */ Console.WriteLine($"IsBinarySearchTree (In Order TraversalAlgo): {IsBinarySearchTreeInOrder(root)}"); }

Output

IsBinarySearchTree (In Order TraversalAlgo): True

Now let's modify Right node's value to 20 and observe:

    static void Main(string[] args)
    {
prev = null; var root = new Node(20); root.Left = new Node(20); root.Right = new Node(20); /* 20 /\ 20 20 */ Console.WriteLine($"IsBinarySearchTree (In Order TraversalAlgo, duplicate node in right): {IsBinarySearchTreeInOrder(root)}"); }

Output

IsBinarySearchTree (In Order TraversalAlgo, duplicate node in right): True

It still says true but that should not be the case. So this method works only when there are no duplicates.


Like 0 People
Last modified on 12 May 2021
Nikhil Joshi

Nikhil Joshi
Ceo & Founder at Dotnetlovers
Atricles: 146
Questions: 16
Given Best Solutions: 16 *

Comments:

No Comments Yet

You are not loggedin, please login or signup to add comments:

Existing User

Login via:

New User



x