Open In App

Day-Stout-Warren algorithm to balance given Binary Search Tree

 Given an unbalanced Binary Search Tree (BST), the task is to convert it into a balanced BST in linear time and without using auxiliary space.

Examples:



Input:               5
                       /  \
                     1   10
                             \
                             20
                               \
                               35
Output:          20
                     /   \
                  5     35
               /   \
            1      10

Input:                 10 
                         / 
                      5
                   /
                 2 
               / 
             1
Output:            5 
                      /  \
                   2    10
                 / 
              1



 

Approach: The algorithm used in this scenario is the Day-Stout-Warren algorithm. The balanced tree formed will be a complete binary tree. Follow the steps below for the implementation of the algorithm.

Illustrations:

Illustration-1: Here the given tree is a left skewed BST

Example-1

Illustration-2: Here it is a non-skewed but unbalanced BST

Example-2

Below is the implementation of the above approach.




// C++ code to balance BST using DSW algorithm.
#include <bits/stdc++.h>
using namespace std;
 
// Defining the structure for TreeNode.
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode()
        : val(0)
        , left(NULL)
        , right(NULL)
    {
    }
    TreeNode(int x)
        : val(x)
        , left(NULL)
        , right(NULL)
    {
    }
    TreeNode(int x, TreeNode* left,
             TreeNode* right)
        : val(x)
        , left(left)
        , right(right)
    {
    }
};
 
// Function to convert input BST
// to right linked list
// known as vine or backbone.
int bstToVine(TreeNode* grand)
{
    int count = 0;
 
    // Make tmp pointer to traverse
    // and right flatten the given BST.
    TreeNode* tmp = grand->right;
 
    // Traverse until tmp becomes NULL
    while (tmp) {
         
        // If left exist for node
        // pointed by tmp then
        // right rotate it.
        if (tmp->left) {
            TreeNode* oldTmp = tmp;
            tmp = tmp->left;
            oldTmp->left = tmp->right;
            tmp->right = oldTmp;
            grand->right = tmp;
        }
 
        // If left dont exists
        // add 1 to count and
        // traverse further right to
        // flatten remaining BST.
        else {
            count++;
            grand = tmp;
            tmp = tmp->right;
        }
    }
 
    return count;
}
 
// Function to compress given tree
// with its root as grand->right.
void compress(TreeNode* grand, int m)
{
    // Make tmp pointer to traverse
    // and compress the given BST.
    TreeNode* tmp = grand->right;
 
    // Traverse and left-rotate root m times
    // to compress given vine form of BST.
    for (int i = 0; i < m; i++) {
        TreeNode* oldTmp = tmp;
        tmp = tmp->right;
        grand->right = tmp;
        oldTmp->right = tmp->left;
        tmp->left = oldTmp;
        grand = tmp;
        tmp = tmp->right;
    }
}
 
// Function to implement the algorithm
TreeNode* balanceBST(TreeNode* root)
{
    // create dummy node with value 0
    TreeNode* grand = new TreeNode(0);
 
    // assign the right of dummy node as our input BST
    grand->right = root;
 
    // get the number of nodes in input BST and
    // simultaneously convert it into right linked list.
    int count = bstToVine(grand);
 
    // gets the height of tree in which all levels
    // are completely filled.
    int h = log2(count + 1);
 
    // get number of nodes until second last level
    int m = pow(2, h) - 1;
 
    // Left rotate for excess nodes at last level
    compress(grand, count - m);
 
    // Left rotation till m becomes 0
    // Step is done as mentioned in algo to
    // make BST balanced.
    for (m = m / 2; m > 0; m /= 2) {
        compress(grand, m);
    }
 
    // return the balanced tree
    return grand->right;
}
 
// Function to print preorder traversal
// of Binary tree.
void preorderTraversal(TreeNode* root)
{
    if (!root)
        return;
    cout << root->val << " ";
    preorderTraversal(root->left);
    preorderTraversal(root->right);
    return;
}
 
// Driver code
int main()
{
    TreeNode* root = new TreeNode(10);
    root->left = new TreeNode(5);
    root->left->left = new TreeNode(2);
    root->left->left->left
        = new TreeNode(1);
     
    // Function call to implement
    // Day-Stout-Warren algorithm
    root = balanceBST(root);
     
    // To print the preorder traversal of BST
    preorderTraversal(root);
 
    return 0;
}




// Java code to balance BST using DSW algorithm.
 
public class DayStout {
    // Defining the structure for TreeNode.
    static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
 
        TreeNode(int val) { this.val = val; }
    }
 
    // Function to convert input BST
    // to right linked list
    // known as vine or backbone.
    static int bstToVine(TreeNode grand)
    {
        int count = 0;
 
        // Make tmp pointer to traverse
        // and right flatten the given BST.
        TreeNode tmp = grand.right;
 
        // Traverse until tmp becomes NULL
        while (tmp != null) {
            // If left exist for node
            // pointed by tmp then
            // right rotate it.
            if (tmp.left != null) {
                TreeNode oldTmp = tmp;
                tmp = tmp.left;
                oldTmp.left = tmp.right;
                tmp.right = oldTmp;
                grand.right = tmp;
            }
 
            // If left dont exists
            // add 1 to count and
            // traverse further right to
            // flatten remaining BST.
            else {
                count++;
                grand = tmp;
                tmp = tmp.right;
            }
        }
 
        return count;
    }
 
    // Function to compress given tree
    // with its root as grand.right.
    static void compress(TreeNode grand, int m)
    {
        // Make tmp pointer to traverse
        // and compress the given BST.
        TreeNode tmp = grand.right;
 
        // Traverse and left-rotate root m times
        // to compress given vine form of BST.
        for (int i = 0; i < m; i++) {
            TreeNode oldTmp = tmp;
            tmp = tmp.right;
            grand.right = tmp;
            oldTmp.right = tmp.left;
            tmp.left = oldTmp;
            grand = tmp;
            tmp = tmp.right;
        }
    }
 
    // Function to calculate the
    // log base 2 of an integer
    static public int log2(int N)
    {
        // calculate log2 N indirectly
        // using log() method
        int result = (int)(Math.log(N) / Math.log(2));
 
        return result;
    }
 
    // Function to implement the algorithm
    static TreeNode balanceBST(TreeNode root)
    {
        // create dummy node with value 0
        TreeNode grand = new TreeNode(0);
 
        // assign the right of dummy node as our input BST
        grand.right = root;
 
        // get the number of nodes in input BST and
        // simultaneously convert it into right linked list.
        int count = bstToVine(grand);
 
        // gets the height of tree in which all levels
        // are completely filled.
        int h = log2(count + 1);
 
        // get number of nodes until second last level
        int m = (int)Math.pow(2, h) - 1;
 
        // Left rotate for excess nodes at last level
        compress(grand, count - m);
 
        // Left rotation till m becomes 0
        // Step is done as mentioned in algo to
        // make BST balanced.
        for (m = m / 2; m > 0; m /= 2) {
            compress(grand, m);
        }
 
        // return the balanced tree
        return grand.right;
    }
 
    // Function to print preorder traversal
    // of Binary tree.
    static void preorderTraversal(TreeNode root)
    {
        if (root == null)
            return;
        System.out.print(root.val + " ");
        preorderTraversal(root.left);
        preorderTraversal(root.right);
        return;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        TreeNode root = new TreeNode(10);
        root.left = new TreeNode(5);
        root.left.left = new TreeNode(2);
        root.left.left.left = new TreeNode(1);
 
        // Function call to implement
        // Day-Stout-Warren algorithm
        root = balanceBST(root);
 
        // To print the preorder traversal of BST
        preorderTraversal(root);
    }
}
 
// This code is contributed by Lovely Jain




// C# code to balance BST using DSW algorithm
using System;
public class GFG {
 
  // Defining the structure for TreeNode.
  class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;
 
    public TreeNode(int val)
    {
      this.val = val;
      left = right = null;
    }
  }
 
  // Function to convert input BST
  // to right linked list
  // known as vine or backbone.
  static int bstToVine(TreeNode grand)
  {
    int count = 0;
 
    // Make tmp pointer to traverse
    // and right flatten the given BST.
    TreeNode tmp = grand.right;
 
    // Traverse until tmp becomes NULL
    while (tmp != null) {
      // If left exist for node
      // pointed by tmp then
      // right rotate it.
      if (tmp.left != null) {
        TreeNode oldTmp = tmp;
        tmp = tmp.left;
        oldTmp.left = tmp.right;
        tmp.right = oldTmp;
        grand.right = tmp;
      }
 
      // If left dont exists
      // add 1 to count and
      // traverse further right to
      // flatten remaining BST.
      else {
        count++;
        grand = tmp;
        tmp = tmp.right;
      }
    }
 
    return count;
  }
 
  // Function to compress given tree
  // with its root as grand.right.
  static void compress(TreeNode grand, int m)
  {
    // Make tmp pointer to traverse
    // and compress the given BST.
    TreeNode tmp = grand.right;
 
    // Traverse and left-rotate root m times
    // to compress given vine form of BST.
    for (int i = 0; i < m; i++) {
      TreeNode oldTmp = tmp;
      tmp = tmp.right;
      grand.right = tmp;
      oldTmp.right = tmp.left;
      tmp.left = oldTmp;
      grand = tmp;
      tmp = tmp.right;
    }
  }
 
  // Function to calculate the
  // log base 2 of an integer
  static public int log2(int N)
  {
    // calculate log2 N indirectly
    // using log() method
    int result = (int)(Math.Log(N) / Math.Log(2));
 
    return result;
  }
 
  // Function to implement the algorithm
  static TreeNode balanceBST(TreeNode root)
  {
    // create dummy node with value 0
    TreeNode grand = new TreeNode(0);
 
    // assign the right of dummy node as our input BST
    grand.right = root;
 
    // get the number of nodes in input BST and
    // simultaneously convert it into right linked list.
    int count = bstToVine(grand);
 
    // gets the height of tree in which all levels
    // are completely filled.
    int h = log2(count + 1);
 
    // get number of nodes until second last level
    int m = (int)Math.Pow(2, h) - 1;
 
    // Left rotate for excess nodes at last level
    compress(grand, count - m);
 
    // Left rotation till m becomes 0
    // Step is done as mentioned in algo to
    // make BST balanced.
    for (m = m / 2; m > 0; m /= 2) {
      compress(grand, m);
    }
 
    // return the balanced tree
    return grand.right;
  }
 
  // Function to print preorder traversal
  // of Binary tree.
  static void preorderTraversal(TreeNode root)
  {
    if (root == null)
      return;
    Console.Write(root.val + " ");
    preorderTraversal(root.left);
    preorderTraversal(root.right);
    return;
  }
 
  static public void Main()
  {
 
    // Code
    TreeNode root = new TreeNode(10);
    root.left = new TreeNode(5);
    root.left.left = new TreeNode(2);
    root.left.left.left = new TreeNode(1);
 
    // Function call to implement
    // Day-Stout-Warren algorithm
    root = balanceBST(root);
 
    // To print the preorder traversal of BST
    preorderTraversal(root);
  }
}
 
// This code is contributed by lokesh(lokeshmvs21).




<script>
// Javascript code to balance BST using DSW algorithm.
 
 
// Defining the structure for TreeNode.
class TreeNode {
    constructor(x = 0, left = null, right = null){
        this.val = x
        this.left = left
        this.right = right
    }
}
 
// Function to convert input BST
// to right linked list
// known as vine or backbone.
function bstToVine(grand) {
    let count = 0;
 
    // Make tmp pointer to traverse
    // and right flatten the given BST.
    let tmp = grand.right;
 
    // Traverse until tmp becomes NULL
    while (tmp) {
 
        // If left exist for node
        // pointed by tmp then
        // right rotate it.
        if (tmp.left) {
            let oldTmp = tmp;
            tmp = tmp.left;
            oldTmp.left = tmp.right;
            tmp.right = oldTmp;
            grand.right = tmp;
        }
 
        // If left dont exists
        // add 1 to count and
        // traverse further right to
        // flatten remaining BST.
        else {
            count++;
            grand = tmp;
            tmp = tmp.right;
        }
    }
 
    return count;
}
 
// Function to compress given tree
// with its root as grand.right.
function compress(grand, m) {
    // Make tmp pointer to traverse
    // and compress the given BST.
    let tmp = grand.right;
 
    // Traverse and left-rotate root m times
    // to compress given vine form of BST.
    for (let i = 0; i < m; i++) {
        let oldTmp = tmp;
        tmp = tmp.right;
        grand.right = tmp;
        oldTmp.right = tmp.left;
        tmp.left = oldTmp;
        grand = tmp;
        tmp = tmp.right;
    }
}
 
// Function to implement the algorithm
function balanceBST(root) {
    // create dummy node with value 0
    let grand = new TreeNode(0);
 
    // assign the right of dummy node as our input BST
    grand.right = root;
 
    // get the number of nodes in input BST and
    // simultaneously convert it into right linked list.
    let count = bstToVine(grand);
 
    // gets the height of tree in which all levels
    // are completely filled.
    let h = Math.log2(count + 1);
 
    // get number of nodes until second last level
    let m = Math.pow(2, h) - 1;
 
    // Left rotate for excess nodes at last level
    compress(grand, count - m);
 
    // Left rotation till m becomes 0
    // Step is done as mentioned in algo to
    // make BST balanced.
    for (m = Math.floor(m / 2); m > 0; m = Math.floor(m / 2)) {
        compress(grand, m);
    }
 
    // return the balanced tree
    return grand.right;
}
 
// Function to print preorder traversal
// of Binary tree.
function preorderTraversal(root) {
    if (!root)
        return;
    document.write(root.val + " ");
    preorderTraversal(root.left);
    preorderTraversal(root.right);
    return;
}
 
// Driver code
 
let root = new TreeNode(10);
root.left = new TreeNode(5);
root.left.left = new TreeNode(2);
root.left.left.left = new TreeNode(1);
 
// Function call to implement
// Day-Stout-Warren algorithm
root = balanceBST(root);
 
// To print the preorder traversal of BST
preorderTraversal(root);
 
// This code is contributed by saurabh_jaiswal.
</script>




# Python code to balance BST using DSW algorithm
import math
 
# Defining the structure for TreeNode
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
 
# Function to convert input BST to right linked list known as vine or backbone.
def bstToVine(grand: TreeNode) -> int:
    count = 0
 
    # Make tmp pointer to traverse and right flatten the given BST
    tmp = grand.right
 
    # while tmp is not null
    while tmp:
 
        # If left exist for node pointed by tmp then right rotate it
        if tmp.left:
            oldTmp = tmp
            tmp = tmp.left
            oldTmp.left = tmp.right
            tmp.right = oldTmp
            grand.right = tmp
 
        # If left dont exists add 1 to count and traverse further right to flatten remaining BST
        else:
            count += 1
            grand = tmp
            tmp = tmp.right
 
    return count
 
# Function to compress given tree with its root as grand.right
def compress(grand: TreeNode, m: int) -> None:
 
    # Make tmp pointer to traverse and compress the given BST
    tmp = grand.right
 
    # Traverse and left-rotate root m times to compress given vine form of BST
    for i in range(m):
        oldTmp = tmp
        tmp = tmp.right
        grand.right = tmp
        oldTmp.right = tmp.left
        tmp.left = oldTmp
        grand = tmp
        tmp = tmp.right
 
# Function to implement the algorithm
def balanceBST(root: TreeNode) -> TreeNode:
 
    # create dummy node with value 0
    grand = TreeNode(0)
 
    # assign the right of dummy node as our input BST
    grand.right = root
 
    #  get the number of nodes in input BST and simultaneously convert it into right linked list.
    count = bstToVine(grand)
 
    # get the height of tree in which all levels are completely filled
    h = int(math.log2(count + 1))
 
    # get number of nodes until second last level
    m = pow(2, h) - 1
 
    # left rotate for excess nodes at last level
    compress(grand, count - m)
 
    # left rotate till m becomes 0
    # Steps is done as mentioned in algorithm to make BST balanced.
    for m in [m // 2**i for i in range(1, h + 1)]:
        compress(grand, m)
 
    # return the root of the balanced binary search tree
    return grand.right
 
# Function to print preorder traversal of Binary tree
def preorderTraversal(root: TreeNode) -> None:
    if not root:
        return
    print(root.val, end=" ")
    preorderTraversal(root.left)
    preorderTraversal(root.right)
    return
 
# Driver code
if __name__ == "__main__":
 
    root = TreeNode(10)
    root.left = TreeNode(5)
    root.left.left = TreeNode(2)
    root.left.left.left = TreeNode(1)
 
    # Function call to implement Day-Stout-Warren algorithm
    root = balanceBST(root)
 
    # To print the preorder traversal of BST
    preorderTraversal(root)

 
 

Output
5 2 1 10 

 

Time Complexity: O(N) where N is the total number of nodes in the BST
Auxiliary Space: O(1)

 


Article Tags :