📜  将正常的BST转换为平衡的BST

📅  最后修改于: 2021-05-25 00:15:19             🧑  作者: Mango

给定一个BST(B inary小号Ť操作搜索REE),其可以是不平衡的,将其转换成具有最小可能高度平衡的BST。

例子 :

Input:
       30
      /
     20
    /
   10
Output:
     20
   /   \
 10     30


Input:
         4
        /
       3
      /
     2
    /
   1
Output:
      3            3           2
    /  \         /  \        /  \
   1    4   OR  2    4  OR  1    3   OR ..
    \          /                   \
     2        1                     4 

Input:
          4
        /   \
       3     5
      /       \
     2         6 
    /           \
   1             7
Output:
       4
    /    \
   2      6
 /  \    /  \
1    3  5    7 

一个简单的解决方案是遍历Inorder中的节点,并一个接一个地插入自平衡BST(如AVL树)中。此解决方案的时间复杂度为O(n Log n),并且不能保证

一个有效的解决方案可以在O(n)时间内以最小可能的高度构造平衡的BST。以下是步骤。

  1. 按顺序遍历给定的BST,并将结果存储在数组中。此步骤需要O(n)时间。请注意,此数组将被排序,因为BST的有序遍历始终会产生排序的序列。
  2. 使用此处讨论的递归方法,根据上面创建的排序数组构建平衡的BST。此步骤还需要O(n)时间,因为我们恰好遍历每个元素一次,处理一个元素需要O(1)时间。

下面是上述步骤的实现。

C++
// C++ program to convert a left unbalanced BST to
// a balanced BST
#include 
using namespace std;
  
struct Node
{
    int data;
    Node* left,  *right;
};
  
/* This function traverse the skewed binary tree and
   stores its nodes pointers in vector nodes[] */
void storeBSTNodes(Node* root, vector &nodes)
{
    // Base case
    if (root==NULL)
        return;
  
    // Store nodes in Inorder (which is sorted
    // order for BST)
    storeBSTNodes(root->left, nodes);
    nodes.push_back(root);
    storeBSTNodes(root->right, nodes);
}
  
/* Recursive function to construct binary tree */
Node* buildTreeUtil(vector &nodes, int start,
                   int end)
{
    // base case
    if (start > end)
        return NULL;
  
    /* Get the middle element and make it root */
    int mid = (start + end)/2;
    Node *root = nodes[mid];
  
    /* Using index in Inorder traversal, construct
       left and right subtress */
    root->left  = buildTreeUtil(nodes, start, mid-1);
    root->right = buildTreeUtil(nodes, mid+1, end);
  
    return root;
}
  
// This functions converts an unbalanced BST to
// a balanced BST
Node* buildTree(Node* root)
{
    // Store nodes of given BST in sorted order
    vector nodes;
    storeBSTNodes(root, nodes);
  
    // Constucts BST from nodes[]
    int n = nodes.size();
    return buildTreeUtil(nodes, 0, n-1);
}
  
// Utility function to create a new node
Node* newNode(int data)
{
    Node* node = new Node;
    node->data = data;
    node->left = node->right = NULL;
    return (node);
}
  
/* Function to do preorder traversal of tree */
void preOrder(Node* node)
{
    if (node == NULL)
        return;
    printf("%d ", node->data);
    preOrder(node->left);
    preOrder(node->right);
}
  
// Driver program
int main()
{
    /* Constructed skewed binary tree is
                10
               /
              8
             /
            7
           /
          6
         /
        5   */
  
    Node* root = newNode(10);
    root->left = newNode(8);
    root->left->left = newNode(7);
    root->left->left->left = newNode(6);
    root->left->left->left->left = newNode(5);
  
    root = buildTree(root);
  
    printf("Preorder traversal of balanced "
            "BST is : \n");
    preOrder(root);
  
    return 0;
}


Java
// Java program to convert a left unbalanced BST to a balanced BST
  
import java.util.*;
  
/* A binary tree node has data, pointer to left child
   and a pointer to right child */
class Node 
{
    int data;
    Node left, right;
  
    public Node(int data) 
    {
        this.data = data;
        left = right = null;
    }
}
  
class BinaryTree 
{
    Node root;
  
    /* This function traverse the skewed binary tree and
       stores its nodes pointers in vector nodes[] */
    void storeBSTNodes(Node root, Vector nodes) 
    {
        // Base case
        if (root == null)
            return;
  
        // Store nodes in Inorder (which is sorted
        // order for BST)
        storeBSTNodes(root.left, nodes);
        nodes.add(root);
        storeBSTNodes(root.right, nodes);
    }
  
    /* Recursive function to construct binary tree */
    Node buildTreeUtil(Vector nodes, int start,
            int end) 
    {
        // base case
        if (start > end)
            return null;
  
        /* Get the middle element and make it root */
        int mid = (start + end) / 2;
        Node node = nodes.get(mid);
  
        /* Using index in Inorder traversal, construct
           left and right subtress */
        node.left = buildTreeUtil(nodes, start, mid - 1);
        node.right = buildTreeUtil(nodes, mid + 1, end);
  
        return node;
    }
  
    // This functions converts an unbalanced BST to
    // a balanced BST
    Node buildTree(Node root) 
    {
        // Store nodes of given BST in sorted order
        Vector nodes = new Vector();
        storeBSTNodes(root, nodes);
  
        // Constucts BST from nodes[]
        int n = nodes.size();
        return buildTreeUtil(nodes, 0, n - 1);
    }
  
    /* Function to do preorder traversal of tree */
    void preOrder(Node node) 
    {
        if (node == null)
            return;
        System.out.print(node.data + " ");
        preOrder(node.left);
        preOrder(node.right);
    }
  
    // Driver program to test the above functions
    public static void main(String[] args) 
    {
         /* Constructed skewed binary tree is
                10
               /
              8
             /
            7
           /
          6
         /
        5   */
        BinaryTree tree = new BinaryTree();
        tree.root = new Node(10);
        tree.root.left = new Node(8);
        tree.root.left.left = new Node(7);
        tree.root.left.left.left = new Node(6);
        tree.root.left.left.left.left = new Node(5);
  
        tree.root = tree.buildTree(tree.root);
        System.out.println("Preorder traversal of balanced BST is :");
        tree.preOrder(tree.root);
    }
}
  
// This code has been contributed by Mayank Jaiswal(mayank_24)


Python3
# Python3 program to convert a left 
# unbalanced BST to a balanced BST 
import sys
import math
  
# A binary tree node has data, pointer to left child 
# and a pointer to right child 
class Node:
    def __init__(self,data):
        self.data=data
        self.left=None
        self.right=None
  
# This function traverse the skewed binary tree and 
# stores its nodes pointers in vector nodes[]
def storeBSTNodes(root,nodes):
      
    # Base case
    if not root:
        return
      
    # Store nodes in Inorder (which is sorted 
    # order for BST) 
    storeBSTNodes(root.left,nodes)
    nodes.append(root)
    storeBSTNodes(root.right,nodes)
  
# Recursive function to construct binary tree 
def buildTreeUtil(nodes,start,end):
      
    # base case 
    if start>end:
        return None
  
    # Get the middle element and make it root 
    mid=(start+end)//2
    node=nodes[mid]
  
    # Using index in Inorder traversal, construct 
    # left and right subtress
    node.left=buildTreeUtil(nodes,start,mid-1)
    node.right=buildTreeUtil(nodes,mid+1,end)
    return node
  
# This functions converts an unbalanced BST to 
# a balanced BST
def buildTree(root):
      
    # Store nodes of given BST in sorted order 
    nodes=[]
    storeBSTNodes(root,nodes)
  
    # Constucts BST from nodes[] 
    n=len(nodes)
    return buildTreeUtil(nodes,0,n-1)
  
# Function to do preorder traversal of tree
def preOrder(root):
    if not root:
        return
    print("{} ".format(root.data),end="")
    preOrder(root.left)
    preOrder(root.right)
  
# Driver code
if __name__=='__main__':
    # Constructed skewed binary tree is 
    #         10 
    #         / 
    #         8 
    #         / 
    #     7 
    #     / 
    #     6 
    #     / 
    # 5 
    root = Node(10)
    root.left = Node(8)
    root.left.left = Node(7)
    root.left.left.left = Node(6)
    root.left.left.left.left = Node(5)
    root = buildTree(root)
    print("Preorder traversal of balanced BST is :")
    preOrder(root)
      
# This code has been contributed by Vikash Kumar 37


C#
using System;
using System.Collections.Generic;
  
// C# program to convert a left unbalanced BST to a balanced BST 
  
/* A binary tree node has data, pointer to left child 
   and a pointer to right child */
public class Node
{
    public int data;
    public Node left, right;
  
    public Node(int data)
    {
        this.data = data;
        left = right = null;
    }
}
  
public class BinaryTree
{
    public Node root;
  
    /* This function traverse the skewed binary tree and 
       stores its nodes pointers in vector nodes[] */
    public virtual void storeBSTNodes(Node root, List nodes)
    {
        // Base case 
        if (root == null)
        {
            return;
        }
  
        // Store nodes in Inorder (which is sorted 
        // order for BST) 
        storeBSTNodes(root.left, nodes);
        nodes.Add(root);
        storeBSTNodes(root.right, nodes);
    }
  
    /* Recursive function to construct binary tree */
    public virtual Node buildTreeUtil(List nodes, int start, int end)
    {
        // base case 
        if (start > end)
        {
            return null;
        }
  
        /* Get the middle element and make it root */
        int mid = (start + end) / 2;
        Node node = nodes[mid];
  
        /* Using index in Inorder traversal, construct 
           left and right subtress */
        node.left = buildTreeUtil(nodes, start, mid - 1);
        node.right = buildTreeUtil(nodes, mid + 1, end);
  
        return node;
    }
  
    // This functions converts an unbalanced BST to 
    // a balanced BST 
    public virtual Node buildTree(Node root)
    {
        // Store nodes of given BST in sorted order 
        List nodes = new List();
        storeBSTNodes(root, nodes);
  
        // Constucts BST from nodes[] 
        int n = nodes.Count;
        return buildTreeUtil(nodes, 0, n - 1);
    }
  
    /* Function to do preorder traversal of tree */
    public virtual void preOrder(Node node)
    {
        if (node == null)
        {
            return;
        }
        Console.Write(node.data + " ");
        preOrder(node.left);
        preOrder(node.right);
    }
  
    // Driver program to test the above functions 
    public static void Main(string[] args)
    {
         /* Constructed skewed binary tree is 
                10 
               / 
              8 
             / 
            7 
           / 
          6 
         / 
        5   */
        BinaryTree tree = new BinaryTree();
        tree.root = new Node(10);
        tree.root.left = new Node(8);
        tree.root.left.left = new Node(7);
        tree.root.left.left.left = new Node(6);
        tree.root.left.left.left.left = new Node(5);
  
        tree.root = tree.buildTree(tree.root);
        Console.WriteLine("Preorder traversal of balanced BST is :");
        tree.preOrder(tree.root);
    }
}
  
  //  This code is contributed by Shrikant13


输出 :

Preorder traversal of balanced BST is : 
7 5 6 8 10