Two nodes of a BST are swapped, correct the BST

Two of the nodes of a Binary Search Tree (BST) are swapped. Fix (or correct) the BST.

Input Tree:
         10
        /  \
       5    8
      / \
     2   20

In the above tree, nodes 20 and 8 must be swapped to fix the tree.  
Following is the output tree
         10
        /  \
       5    20
      / \
     2   8

The inorder traversal of a BST produces a sorted array. So a simple method is to store inorder traversal of the input tree in an auxiliary array. Sort the auxiliary array. Finally, insert the auxiilary array elements back to the BST, keeping the structure of the BST same. Time complexity of this method is O(nLogn) and auxiliary space needed is O(n).

We can solve this in O(n) time and with a single traversal of the given BST. Since inorder traversal of BST is always a sorted array, the problem can be reduced to a problem where two elements of a sorted array are swapped. There are two cases that we need to handle:

1. The swapped nodes are not adjacent in the inorder traversal of the BST.

 For example, Nodes 5 and 25 are swapped in {3 5 7 8 10 15 20 25}. 
 The inorder traversal of the given tree is 3 25 7 8 10 15 20 5 

If we observe carefully, during inorder traversal, we find node 7 is smaller than the previous visited node 25. Here save the context of node 25 (previous node). Again, we find that node 5 is smaller than the previous node 20. This time, we save the context of node 5 ( current node ). Finally swap the two node’s values.

2. The swapped nodes are adjacent in the inorder traversal of BST.

  For example, Nodes 7 and 8 are swapped in {3 5 7 8 10 15 20 25}. 
  The inorder traversal of the given tree is 3 5 8 7 10 15 20 25 

Unlike case #1, here only one point exists where a node value is smaller than previous node value. e.g. node 7 is smaller than node 8.

How to Solve? We will maintain three pointers, first, middle and last. When we find the first point where current node value is smaller than previous node value, we update the first with the previous node & middle with the current node. When we find the second point where current node value is smaller than previous node value, we update the last with the current node. In case #2, we will never find the second point. So, last pointer will not be updated. After processing, if the last node value is null, then two swapped nodes of BST are adjacent.

Following is C implementation of the given code.

// Two nodes in the BST's swapped, correct the BST.
#include <stdio.h>
#include <stdlib.h>

/* A binary tree node has data, pointer to left child
   and a pointer to right child */
struct node
{
    int data;
    struct node *left, *right;
};

// A utility function to swap two integers
void swap( int* a, int* b )
{
    int t = *a;
    *a = *b;
    *b = t;
}

/* Helper function that allocates a new node with the
   given data and NULL left and right pointers. */
struct node* newNode(int data)
{
    struct node* node = (struct node *)malloc(sizeof(struct node));
    node->data = data;
    node->left = NULL;
    node->right = NULL;
    return(node);
}

// This function does inorder traversal to find out the two swapped nodes.
// It sets three pointers, first, middle and last.  If the swapped nodes are
// adjacent to each other, then first and middle contain the resultant nodes
// Else, first and last contain the resultant nodes
void correctBSTUtil( struct node* root, struct node** first,
                     struct node** middle, struct node** last,
                     struct node** prev )
{
    if( root )
    {
        // Recur for the left subtree
        correctBSTUtil( root->left, first, middle, last, prev );

        // If this node is smaller than the previous node, it's violating
        // the BST rule.
        if (*prev && root->data < (*prev)->data)
        {
            // If this is first violation, mark these two nodes as
            // 'first' and 'middle'
            if ( !*first )
            {
                *first = *prev;
                *middle = root;
            }

            // If this is second violation, mark this node as last
            else
                *last = root;
        }

        // Mark this node as previous
        *prev = root;

        // Recur for the right subtree
        correctBSTUtil( root->right, first, middle, last, prev );
    }
}

// A function to fix a given BST where two nodes are swapped.  This
// function uses correctBSTUtil() to find out two nodes and swaps the
// nodes to fix the BST
void correctBST( struct node* root )
{
    // Initialize pointers needed for correctBSTUtil()
    struct node *first, *middle, *last, *prev;
    first = middle = last = prev = NULL;

    // Set the poiters to find out two nodes
    correctBSTUtil( root, &first, &middle, &last, &prev );

    // Fix (or correct) the tree
    if( first && last )
        swap( &(first->data), &(last->data) );
    else if( first && middle ) // Adjacent nodes swapped
        swap( &(first->data), &(middle->data) );

    // else nodes have not been swapped, passed tree is really BST.
}

/* A utility function to print Inoder traversal */
void printInorder(struct node* node)
{
    if (node == NULL)
        return;
    printInorder(node->left);
    printf("%d ", node->data);
    printInorder(node->right);
}

/* Driver program to test above functions*/
int main()
{
    /*   6
        /  \
       10    2
      / \   / \
     1   3 7  12
     10 and 2 are swapped
    */

    struct node *root = newNode(6);
    root->left        = newNode(10);
    root->right       = newNode(2);
    root->left->left  = newNode(1);
    root->left->right = newNode(3);
    root->right->right = newNode(12);
    root->right->left = newNode(7);

    printf("Inorder Traversal of the original tree \n");
    printInorder(root);

    correctBST(root);

    printf("\nInorder Traversal of the fixed tree \n");
    printInorder(root);

    return 0;
}

Output:

Inorder Traversal of the original tree
1 10 3 6 7 2 12
Inorder Traversal of the fixed tree
1 2 3 6 7 10 12

Time Complexity: O(n)

See this for different test cases of the above code.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above





  • AlienOnEarth

    @Geeksforgeeks:

    Another simpler solution:

    1.) use isBST routine to check whether the given tree is BST.

    2.) if so, do not fix tree.

    3.) if not BST, initialise 2 pointers first and last to nodes to be fixed.

    4.) fix BST and print.

    C program for the above algorithm is as below:

    // A program to check if a given binary tree is complete or not

    #include

    #include

    #include

    #include

    struct node * first=NULL;

    struct node * last=NULL;

    /* A binary tree node has data, pointer to left child

    and a pointer to right child */

    struct node

    {

    int data;

    struct node* left;

    struct node* right;

    };

    void inorder(struct node *root)

    {

    if(root == NULL)

    return;

    inorder(root->left);

    printf(“%d, “,root->data);

    inorder(root->right);

    }

    bool isBST(struct node *root, int min, int max)

    {

    if(root == NULL)

    return true;

    if (root->datadata>max)

    {

    if(min!=INT_MIN && root->datadata>max)

    {

    if(first == NULL)

    {

    first = root;

    return false;

    }

    if(last == NULL)

    {

    last = root;

    return false;

    }

    }

    return false;

    }

    bool l = isBST(root->left, min, root->data);

    bool r = isBST(root->right, root->data+1, max);

    return l&&r;

    }

    void fixBST(struct node *root)

    {

    isBST(root,INT_MIN,INT_MAX) ;

    if(first!=NULL && last!=NULL)

    {

    // swap

    int t = first->data;

    first->data = last->data;

    last->data = t;

    }

    }

    /* Helper function that allocates a new node with the

    given data and NULL left and right pointers. */

    struct node* newNode(int data)

    {

    struct node* node = (struct node*)

    malloc(sizeof(struct node));

    node->data = data;

    node->left = NULL;

    node->right = NULL;

    return(node);

    }

    /* Driver program to test above functions*/

    int main()

    {

    /* Let us construct the following Binary Tree which

    is not a complete Binary Tree

    1

    /

    2 3

    /

    4 5 6

    */

    struct node *root = newNode(10);

    root->left = newNode(5);

    root->right = newNode(8);

    root->left->left = newNode(2);

    root->left->right = newNode(20);

    // root->right->left = newNode(7);

    // root->right->right = newNode(6);

    inorder(root);

    printf(“n”);

    fixBST(root);

    inorder(root);

    return 0;

    }

  • abubakar

    struct node *root = newNode(15);
    root->left = newNode(6);
    root->right = newNode(20);
    root->left->left = newNode(10);
    root->left->right = newNode(7);
    root->left->left->left = newNode(1);
    root->left->left->right = newNode(3);
    it does not work for this input

    • abubakar

      Input is wrong

  • M C S KRISHNA

    O(n) solution:

    void CorrectBSTMine (struct node * root)
    {
    static struct node *temp1 = NULL;
    static struct node *temp2 = NULL;
    int temp;

    if (root != NULL && (temp1 == NULL || temp2 == NULL) ) {
    if (root->left != NULL && root->left->data > root->data) {

    if (temp1 == NULL) {
    temp1 = root->left;
    }
    else {
    temp2 = root->left;
    }
    }

    if (root->right != NULL && root->right->data data) {
    if (temp1 == NULL) {
    temp1 = root->right;
    }
    else {
    temp2 = root->right;
    }
    }
    CorrectBSTMine(root->left);
    CorrectBSTMine(root->right);
    }

    if (temp1 != NULL || temp2 != NULL) {
    temp = temp1->data;
    temp1->data = temp2->data;
    temp2->data = temp;
    }
    }

  • rahul tibrewal

    what if the first element of the inorder traversal, or the leftmost element has to be swapped, you have assumed that it is correct, am i wrong?

  • mrn

    void correctSwappedTree(Node *root,Node *&first,Node *&second,Node *&prev){

    if(root==NULL)

    return;

    correctSwappedTree(root->l,first,second,prev);

    if(prev!=NULL && root->v v)

    {

    if(!first)

    {first=prev;second=root;}

    else

    second=root;

    }

    prev=root;

    correctSwappedTree(root->r,first,second,prev);

    }

  • ubiquitous

    create a binary tree with the data 10, 5 ,7,6,8,9. Now you swap 7,9. Check the implementation , it will give you wrong answer. Thanks.

  • illuminati

    simple method but stucked in implementation… ๐Ÿ˜›

  • Ishita

    We don’t need three pointers first, middle and last. We can just do with two.

     
    
    if ( !*first )
                {
                    *first = *prev;
                    *last = root;
                }
     
                else
                    *last = root;
     

    Now just swap data at first and last.

  • Someone

    Can someone give me a working java solution to this? How to use double pointers in java?

     
    /* Paste your code here (You may delete these lines if not writing code) */
     
  • Bond

    I think we can save ourselves from recursion using the iterative in-order traversal returning “pointer to the node”. It would be lot easier to handle. Just run a loop and maintain three pointers as suggested.
    I agree it would not allow you to swap the pointers, but it would be easier to swap the values and to visualize.

  • abhishek08aug

    Intelligent ๐Ÿ˜€

    • ABHINAV

      Please tell me if you find my method a little faulty

      It may help me

      My Comment is 2 comments below

       
      /* Paste your code here (You may delete these lines if not writing code) */
       
  • apsc

    in the simple method after sorting the auxiliary array, how do you insert elements back keeping the structure same?

  • ABHINAV

    I think for this not for travelling whole tree just mark the positions when we find them and break if we find the two defaulty positions

    please comment on this
    /*
    node *ptr1=null,*ptr 2=null;
    function tree(node)
    {
    leftnode=node->left;
    rightnode=node->right;

    if(node->left==null && node->right==null)
    return;

    if(leftnode->info>node->info || rightnode->infoinfo)
    {
    if(*ptr1!=null)
    *ptr1=node;
    else if(*ptr2!=null)
    *ptr2=node;
    }
    if(*ptr2!=null && *ptr1!=null)
    return;
    else
    tree(leftnode);
    tree(rightnode);
    }

    */

    • ABHINAV

      *if(leftnode->info>node->info || rightnode-><infoinfo)

      means if we find default node in the BST

  • Amit
     
    /* Paste your code here (You may delete these lines if not writing code) */
    #include <stdio.h>
    #include <stdlib.h>
    #include<limits.h>
    struct node
    {
        int data;
        struct node *left, *right;
    };
    struct node * first = NULL;
    struct node * second = NULL;
    void swap( int* a, int* b )
    {
        int t = *a;
        *a = *b;
        *b = t;
    }
    struct node* newNode(int data)
    {
        struct node* node = (struct node *)malloc(sizeof(struct node));
        node->data = data;
        node->left = NULL;
        node->right = NULL;
        return(node);
    }
    void printInorder(struct node* node)
    {
        if (node == NULL)
            return;
        printInorder(node->left);
        printf("%d ", node->data);
        printInorder(node->right);
    }
    void correctBST(struct node * root, int min, int max){
         if(root== NULL){
                   return;
         }
         correctBST(root->left,min,root->data-1);
         if(root->data < min || root->data > max){
                       if(first == NULL){
                                first = root;
                       }
                       else{
                            second = root;
                       }
         }
         correctBST(root->right,root->data+1,max);
    }
    int main()
    {
        /*   6
            /  \
           10    2
          / \   / \
         1   3 7  12
         10 and 2 are swapped
        */
     
        struct node *root = newNode(6);
        root->left        = newNode(10);
        root->right       = newNode(2);
        root->left->left  = newNode(1);
        root->left->right = newNode(3);
        root->right->right = newNode(12);
        root->right->left = newNode(7);
     
        printf("Inorder Traversal of the original tree \n");
        printInorder(root);
     
        correctBST(root,INT_MIN,INT_MAX);
        swap(first,second);
        printf("\nInorder Traversal of the fixed tree \n");
        printInorder(root);
        getchar();
        return 0;
    }
    
     
    • Amit

      void correctBST(struct node * root, int min, int max){
      if(root== NULL){
      return;
      }
      correctBST(root->left,min,root->data-1);
      if(root->data data > max){
      if(first == NULL){
      first = root;
      }
      else{
      second = root;
      }
      }
      correctBST(root->right,root->data+1,max);
      }

  • srinichal
     
    void Tree::BSTNormal(TNode* node)
    {
    	if(node==NULL) return;
    	int max = node->val;
    	int min = node->val;
    	GetMax(node->left,&max);
    	GetMin(node->right,&min);
    	if(min < max)
    		swap(node,max,min);
    	else if(node->val <= max)
    		swap(node,node->val,max);
    	else if(node->val >= min)
    		swap(node,node->val,min);
    	BSTNormal(node->left);
    	BSTNormal(node->right);
    } 
  • firefist

    i thought i should try swapping the pointers instead of data.
    please let me know if it has any erros.

     
    static void Main(){
                BinaryTree obj = new BinaryTree();
    	    Node beta = null;
                Node alpha = null;
                obj.FindSwappedNodes(obj.Root, ref alpha, ref beta);           
                Node alphaParent = null;
                Node betaParent = null;
                bool isAlphaFound = false;
                bool isBetaFound = false;
                obj.Root = obj.SwapBSTNodes(obj.Root, alpha, beta, ref isAlphaFound,ref isBetaFound, ref alphaParent, ref betaParent);
    
    } 
    public void FindSwappedNodes(Node root,ref Node alpha,ref Node beta)
            {
                Node prev = null;
                Stack<Node> s = new Stack<Node>();
                while (true)
                {
                    while (root != null)
                    {
                        s.Push(root);
                        root = root.Left;
                    }
                    if (s.Count <= 0)
                        return;
                    root = s.Pop();
                    if (prev != null)
                    {
                        if (prev.Data > root.Data)
                        {
                            if (alpha == null)
                                alpha = prev;
                            else
                            {
                                beta = root;
                            }
                        }
    
                    }
    
                    Console.Write(root.Data + "  ");
                    prev = root;
                    root = root.Right;
                }
            }
    
    public Node SwapBSTNodes(Node root, Node alpha, Node beta,ref bool isAlphaFound,ref bool isBetaFound,ref Node alphaParent,ref Node betaParent)
            {
                if (root == null)
                    return null;            
                if (!(isAlphaFound == true && isBetaFound == true))
                {
                    if (root.Left == alpha || root.Right == alpha )
                    {
                        isAlphaFound =true;
                        alphaParent = root;
                    }
                    if (root.Left == beta || root.Right == beta )
                    {
                        isBetaFound =true;
                        betaParent = root;
                    }
                    if (isAlphaFound == true && isBetaFound == true)
                    {
                        Node temp = null;
                        if (alphaParent.Left == alpha && betaParent.Left == beta)
                        {
                            alphaParent.Left = beta;
                            betaParent.Left = alpha;             
                        }
                        if (alphaParent.Right == alpha && betaParent.Left == beta)
                        {
                            alphaParent.Right = beta;
                            betaParent.Left = alpha;
                        }
                        if (alphaParent.Left == alpha && betaParent.Right == beta)
                        {
                            alphaParent.Left = beta;
                            betaParent.Right = alpha;
                        }
                        if (alphaParent.Right == alpha && betaParent.Right == beta)
                        {
                            alphaParent.Right = beta;
                            betaParent.Right = alpha;
                        }
                        temp = beta.Left;
                        beta.Left = alpha.Left;
                        alpha.Left = temp;
                        temp = beta.Right;
                        beta.Right = alpha.Right;
                        alpha.Right = temp;
                        return root;
                    }
    
                }
                root.Left = SwapBSTNodes(root.Left, alpha, beta,ref isAlphaFound,ref isBetaFound, ref alphaParent, ref betaParent);
                root.Right = SwapBSTNodes(root.Right, alpha, beta,ref isAlphaFound,ref isBetaFound, ref alphaParent, ref betaParent);
                return root;
            }
    
    
     
  • latha

    /*
    The solution for this one is after obtaining the inorder traversal of bst then use two pointers first and last nodes and increment first upto u get a greater element than that one, and decrement last upto u get a smaller element and then swap both the elements.
    Eg:
    3 25 6 8 10 5 28
    / \last
    first and store the first add in some variable let us say first1.
    compare 3 with 25 3 less so inc after inc first
    3 25 6 8 10 5 28
    / \
    first last
    now compare 25 with 6 greater so stop here now compare 28 with 5 using a temp pointer 25 is greater so dec last
    3 25 6 8 10 5 28
    / \
    first last
    now compare 5 with 10 5 is less and now stop and swap first and last.
    after swapping
    3 5 6 8 10 25 28
    thank u:)
    */

    • latha

      /*sry first nd last are not pointed correctly ..
      in first case first points to 3 and last points to 28.
      in second case first points to 25 and last points to 28.
      in third case first points to 25 and last points to 5.
      now then swap..
      thank u:)
      */

  • vasavi

    nice……but……it is not a good program…..u have to try again

  • Anant Upadhyay

    good solution

     
    /* Paste your code here (You may delete these lines if not writing code) */
     
    • vasavi

      fine

       
      
       
  • Karthick

    Hi,
    I think the following approach can be used if the nodes as such have to be swapped and not the data alone.

    1) First, find the two misplaced nodes along with their parents(n1,p1,n2,p2) This can be implemented by slighly modifying the code for checking if the given tree is a BST.
    2) Swap the children of the nodes n1 and n2.
    3) Make p1 point to n2 and p2 point to n1.
    There is one small catch in the third step – if n1 is the parent of n2, it has to handled a bit separately.

    Thanks,
    Karthick

    • Karthick

      The following code can also be used to find the two misplaced nodes.
      This is a slight modification of checking if the given tree is a BST.

      void findMisplacedNodes(node *root,int low,int high,node *&n1,node *&n2){
      if(!root)
      return;
      findMisplacedNodes(root->left,low,root->data,n1,n2);
      if(root->datadata>high){
      if(!n1)
      n1=root;
      else
      n2=root;
      }
      findMisplacedNodes(root->right,root->data,high,n1,n2);
      return;
      }

      If anything is wrong, please comment.

      Thanks,

      • Karthick

        Sorry, I tried the sourcecode tag with c++ and it is not working.
        Reposting the code.

         
        void findMisplacedNodes(node *root,int low,int high,node *&n1,node *&n2){
        	if(!root)
        		return;
        	findMisplacedNodes(root->left,low,root->data,n1,n2);
        	if(root->data<low || root->data>high){
        		if(!n1)
        			n1=root;
        		else
        			n2=root;
        	}
        	findMisplacedNodes(root->right,root->data,high,n1,n2);
        	return;
        }
         

        Thanks,

        • Aashish

          Your approach doesn’t work for:
          10,5,15,3.
          Swap nodes 5 and 3.

          • Karthick

            Yes. Thanks for pointing that out. :)

        • vasavi

          It is Somewhat complicated so U have write a program…..that is Understand by Users not u…k……..good luck