📜  二叉树到二叉搜索树的转换

📅  最后修改于: 2021-05-24 23:13:49             🧑  作者: Mango

给定二叉树,将其转换为二叉搜索树。转换必须采用保留二叉树原始结构的方式进行。

例子。

Example 1
Input:
          10
         /  \
        2    7
       / \
      8   4
Output:
          8
         /  \
        4    10
       / \
      2   7


Example 2
Input:
          10
         /  \
        30   15
       /      \
      20       5
Output:
          15
         /  \
       10    20
       /      \
      5        30

解决方案
以下是将二进制树转换为二进制搜索树的3个步骤的解决方案。
1)创建一个临时数组arr [],用于存储树的有序遍历。此步骤需要O(n)时间。
2)对临时数组arr []进行排序。此步骤的时间复杂度取决于排序算法。在以下实现中,使用了快速排序,需要花费(n ^ 2)的时间。可以使用堆排序或合并排序在O(nLogn)时间完成此操作。
3)再次进行树的有序遍历,并将数组元素一一复制到树节点。此步骤需要O(n)时间。

以下是上述方法的C实现。以下代码突出显示了要转换的主要函数。

C
/* A program to convert Binary Tree to Binary Search Tree */
#include 
#include 
  
/* A binary tree node structure */
struct node {
    int data;
    struct node* left;
    struct node* right;
};
  
/* A helper function that stores inorder traversal of a tree rooted
  with node */
void storeInorder(struct node* node, int inorder[], int* index_ptr)
{
    // Base Case
    if (node == NULL)
        return;
  
    /* first store the left subtree */
    storeInorder(node->left, inorder, index_ptr);
  
    /* Copy the root's data */
    inorder[*index_ptr] = node->data;
    (*index_ptr)++; // increase index for next entry
  
    /* finally store the right subtree */
    storeInorder(node->right, inorder, index_ptr);
}
  
/* A helper function to count nodes in a Binary Tree */
int countNodes(struct node* root)
{
    if (root == NULL)
        return 0;
    return countNodes(root->left) + countNodes(root->right) + 1;
}
  
// Following function is needed for library function qsort()
int compare(const void* a, const void* b)
{
    return (*(int*)a - *(int*)b);
}
  
/* A helper function that copies contents of arr[] to Binary Tree. 
   This function basically does Inorder traversal of Binary Tree and 
   one by one copy arr[] elements to Binary Tree nodes */
void arrayToBST(int* arr, struct node* root, int* index_ptr)
{
    // Base Case
    if (root == NULL)
        return;
  
    /* first update the left subtree */
    arrayToBST(arr, root->left, index_ptr);
  
    /* Now update root's data and increment index */
    root->data = arr[*index_ptr];
    (*index_ptr)++;
  
    /* finally update the right subtree */
    arrayToBST(arr, root->right, index_ptr);
}
  
// This function converts a given Binary Tree to BST
void binaryTreeToBST(struct node* root)
{
    // base case: tree is empty
    if (root == NULL)
        return;
  
    /* Count the number of nodes in Binary Tree so that
       we know the size of temporary array to be created */
    int n = countNodes(root);
  
    // Create a temp array arr[] and store inorder traversal of tree in arr[]
    int* arr = new int[n];
    int i = 0;
    storeInorder(root, arr, &i);
  
    // Sort the array using library function for quick sort
    qsort(arr, n, sizeof(arr[0]), compare);
  
    // Copy array elements back to Binary Tree
    i = 0;
    arrayToBST(arr, root, &i);
  
    // delete dynamically allocated memory to avoid meory leak
    delete[] arr;
}
  
/* Utility function to create a new Binary Tree node */
struct node* newNode(int data)
{
    struct node* temp = new struct node;
    temp->data = data;
    temp->left = NULL;
    temp->right = NULL;
    return temp;
}
  
/* Utility function to print inorder traversal of Binary Tree */
void printInorder(struct node* node)
{
    if (node == NULL)
        return;
  
    /* first recur on left child */
    printInorder(node->left);
  
    /* then print the data of node */
    printf("%d ", node->data);
  
    /* now recur on right child */
    printInorder(node->right);
}
  
/* Driver function to test above functions */
int main()
{
    struct node* root = NULL;
  
    /* Constructing tree given in the above figure
          10
         /  \
        30   15
       /      \
      20       5   */
    root = newNode(10);
    root->left = newNode(30);
    root->right = newNode(15);
    root->left->left = newNode(20);
    root->right->right = newNode(5);
  
    // convert Binary Tree to BST
    binaryTreeToBST(root);
  
    printf("Following is Inorder Traversal of the converted BST: \n");
    printInorder(root);
  
    return 0;
}


Python
# Program to convert binary tree to BST
  
# A binary tree node
class Node:
      
    # Constructor to create a new node
    def __init__(self, data):
        self.data = data 
        self.left = None
        self.right = None
  
# Helper function to store the inroder traversal of a tree
def storeInorder(root, inorder):
      
    # Base Case
    if root is None:
        return 
      
    # First store the left subtree
    storeInorder(root.left, inorder)
      
    # Copy the root's data
    inorder.append(root.data)
  
    # Finally store the right subtree
    storeInorder(root.right, inorder)
  
# A helper funtion to count nodes in a binary tree
def countNodes(root):
    if root is None:
        return 0
  
    return countNodes(root.left) + countNodes(root.right) + 1
  
# Helper function that copies contents of sorted array 
# to Binary tree
def arrayToBST(arr, root):
  
    # Base Case
    if root is None:
        return 
      
    # First update the left subtree
    arrayToBST(arr, root.left)
  
    # now update root's data delete the value from array
    root.data = arr[0]
    arr.pop(0)
  
    # Finally update the right subtree
    arrayToBST(arr, root.right)
  
# This function converts a given binary tree to BST
def binaryTreeToBST(root):
      
    # Base Case: Tree is empty
    if root is None:
        return 
      
    # Count the number of nodes in Binary Tree so that 
    # we know the size of temporary array to be created
    n = countNodes(root)
  
    # Create the temp array and store the inorder traveral 
    # of tree 
    arr = []
    storeInorder(root, arr)
      
    # Sort the array
    arr.sort()
  
    # copy array elements back to binary tree
    arrayToBST(arr, root)
  
# Print the inorder traversal of the tree
def printInorder(root):
    if root is None:
        return
    printInorder(root.left)
    print root.data, 
    printInorder(root.right)
  
# Driver program to test above function
root = Node(10)
root.left = Node(30)
root.right = Node(15)
root.left.left = Node(20)
root.right.right = Node(5)
  
# Convert binary tree to BST 
binaryTreeToBST(root)
  
print "Following is the inorder traversal of the converted BST"
printInorder(root)
  
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)


输出:

Following is Inorder Traversal of the converted BST:
5 10 15 20 30

复杂度分析:

  • 时间复杂度: O(nlogn)。
    这是我们在第一次有序遍历后使用的排序算法的复杂性,其余操作在线性时间内进行。
  • 辅助空间: O(n)。
    使用数据结构“数组”存储有序遍历。

我们将介绍针对此问题的另一种方法,该方法使用O(树的高度)多余的空间来转换树。