📌  相关文章
📜  合并具有恒定额外空间的两个BST

📅  最后修改于: 2021-04-24 14:53:57             🧑  作者: Mango

给定两个Binary Search Tree(BST),以排序形式打印两个BST的元素。
注意:这两个BST都没有任何公共元素。

例子:

Input
First BST: 
       3
    /     \
   1       5
Second BST:
    4
  /   \
2       6
Output: 1 2 3 4 5 6

Input:
First BST: 
          8
         / \
        2   10
       /
      1
Second BST: 
          5
         / 
        3  
       /
      0
Output: 0 1 2 3 5 8 10

这个想法是利用树的最左边的元素(顺序遍历中的第一个元素)是BST中最小的元素这一事实。因此,我们为两棵树都计算了该值并打印了较小的树,现在我们从相应的树中删除此打印元素并进行更新。然后,我们用更新的树递归地调用我们的函数。我们执行此操作,直到其中一棵树枯竭为止。现在,我们简单地打印另一棵树的有序遍历。

下面是上述方法的实现:

C++
// C++ implementation of above approach
#include 
using namespace std;
 
// Structure of a BST Node
class Node {
public:
    int data;
    Node* left;
    Node* right;
    Node(int x)
    {
        data = x;
        left = right = NULL;
    }
};
 
// A utility function to print
// Inorder traversal of a Binary Tree
void inorder(Node* root)
{
    if (root != NULL) {
        inorder(root->left);
        cout << root->data << " ";
        inorder(root->right);
    }
}
 
// The function to print data
// of two BSTs in sorted order
void merge(Node* root1, Node* root2)
{
    // Base cases
    if (!root1 && !root2)
        return;
 
    // If the first tree is exhausted
    // simply print the inorder
    // traversal of the second tree
    if (!root1) {
        inorder(root2);
        return;
    }
 
    // If second tree is exhausted
    // simply print the inoreder
    // traversal of the first tree
    if (!root2) {
        inorder(root1);
        return;
    }
 
    // A temporary pointer currently
    // pointing to root of first tree
    Node* temp1 = root1;
 
    // previous pointer to store the
    // parent of temporary pointer
    Node* prev1 = NULL;
 
    // Traverse through the first tree until you reach
    // the leftmost element, which is the first element
    // of the tree in the inorder traversal.
    // This is the least element of the tree
    while (temp1->left) {
        prev1 = temp1;
        temp1 = temp1->left;
    }
 
    // Another temporary pointer currently
    // pointing to root of second tree
    Node* temp2 = root2;
 
    // Previous pointer to store the
    // parent of second temporary pointer
    Node* prev2 = NULL;
 
    // Traverse through the second tree until you reach
    // the leftmost element, which is the first element of
    // the tree in inorder traversal.
    // This is the least element of the tree.
    while (temp2->left) {
        prev2 = temp2;
        temp2 = temp2->left;
    }
 
    // Compare the least current least
    // elements of both the tree
    if (temp1->data <= temp2->data) {
 
        // If first tree's element is smaller print it
        cout << temp1->data << " ";
 
        // If the node has no parent, that
        // means this node is the root
        if (prev1 == NULL) {
 
            // Simply make the right
            // child of the root as new root
            merge(root1->right, root2);
        }
 
        // If node has a parent
        else {
 
            // As this node is the leftmost node,
            // it is certain that it will not have
            // a let child so we simply assign this
            // node's right pointer, which can be
            // either null or not, to its parent's left
            // pointer. This statement is
            // just doing the task of deleting the node
 
            prev1->left = temp1->right;
 
            // recursively call the merge
            // function with updated tree
            merge(root1, root2);
        }
    }
    else {
 
        cout << temp2->data << " ";
 
        // If the node has no parent, that
        // means this node is the root
        if (prev2 == NULL) {
 
            // Simply make the right child
            // of root as new root
            merge(root1, root2->right);
        }
 
        // If node has a parent
        else {
            prev2->left = temp2->right;
 
            // Recursively call the merge
            // function with updated tree
            merge(root1, root2);
        }
    }
}
 
// Driver Code
int main()
{
    Node *root1 = NULL, *root2 = NULL;
    root1 = new Node(3);
    root1->left = new Node(1);
    root1->right = new Node(5);
    root2 = new Node(4);
    root2->left = new Node(2);
    root2->right = new Node(6);
 
    // Print sorted nodes of both trees
    merge(root1, root2);
 
    return 0;
}


Java
// Java implementation of above approach
import java.util.*;
 
class GFG{
   
// Structure of a BST Node
static class Node
{
    int data;
    Node left;
    Node right;
};
 
static Node newNode(int num)
{
    Node temp = new Node();
    temp.data = num;
    temp.left = temp.right = null;
    return temp;
}
 
// A utility function to print
// Inorder traversal of a Binary Tree
static void inorder(Node root)
{
    if (root != null)
    {
        inorder(root.left);
        System.out.print(root.data + " ");
        inorder(root.right);
    }
}
 
// The function to print data
// of two BSTs in sorted order
static void merge(Node root1, Node root2)
{
     
    // Base cases
    if (root1 == null && root2 == null)
        return;
 
    // If the first tree is exhausted
    // simply print the inorder
    // traversal of the second tree
    if (root1 == null)
    {
        inorder(root2);
        return;
    }
 
    // If second tree is exhausted
    // simply print the inoreder
    // traversal of the first tree
    if (root2 == null)
    {
        inorder(root1);
        return;
    }
 
    // A temporary pointer currently
    // pointing to root of first tree
    Node temp1 = root1;
 
    // previous pointer to store the
    // parent of temporary pointer
    Node prev1 = null;
 
    // Traverse through the first tree
    // until you reach the leftmost element,
    // which is the first element of the tree
    // in the inorder traversal.
    // This is the least element of the tree
    while (temp1.left != null)
    {
        prev1 = temp1;
        temp1 = temp1.left;
    }
 
    // Another temporary pointer currently
    // pointing to root of second tree
    Node temp2 = root2;
 
    // Previous pointer to store the
    // parent of second temporary pointer
    Node prev2 = null;
 
    // Traverse through the second tree
    // until you reach the leftmost element,
    // which is the first element of
    // the tree in inorder traversal.
    // This is the least element of the tree.
    while (temp2.left != null)
    {
        prev2 = temp2;
        temp2 = temp2.left;
    }
 
    // Compare the least current least
    // elements of both the tree
    if (temp1.data <= temp2.data)
    {
         
        // If first tree's element is
        // smaller print it
        System.out.print(temp1.data + " ");
 
        // If the node has no parent, that
        // means this node is the root
        if (prev1 == null)
        {
             
            // Simply make the right
            // child of the root as new root
            merge(root1.right, root2);
        }
 
        // If node has a parent
        else
        {
             
            // As this node is the leftmost node,
            // it is certain that it will not have
            // a let child so we simply assign this
            // node's right pointer, which can be
            // either null or not, to its parent's left
            // pointer. This statement is
            // just doing the task of deleting the node
            prev1.left = temp1.right;
 
            // recursively call the merge
            // function with updated tree
            merge(root1, root2);
        }
    }
    else
    {
        System.out.print(temp2.data + " ");
 
        // If the node has no parent, that
        // means this node is the root
        if (prev2 == null)
        {
             
            // Simply make the right child
            // of root as new root
            merge(root1, root2.right);
        }
 
        // If node has a parent
        else
        {
            prev2.left = temp2.right;
 
            // Recursively call the merge
            // function with updated tree
            merge(root1, root2);
        }
    }
}
 
// Driver Code
public static void main(String args[])
{
    Node root1 = null, root2 = null;
     
    root1 = newNode(3);
    root1.left = newNode(1);
    root1.right = newNode(5);
     
    root2 = newNode(4);
    root2.left = newNode(2);
    root2.right = newNode(6);
 
    // Print sorted nodes of both trees
    merge(root1, root2);
}
}
 
// This code is contributed by ipg2016107


Python3
# Python3 implementation of above approach
 
# Node of the binary tree
class node:
     
    def __init__ (self, key):
         
        self.data = key
        self.left = None
        self.right = None
 
# A utility function to print
# Inorder traversal of a Binary Tree
def inorder(root):
     
    if (root != None):
        inorder(root.left)
        print(root.data, end = " ")
        inorder(root.right)
 
# The function to print data
# of two BSTs in sorted order
def merge(root1, root2):
     
    # Base cases
    if (not root1 and not root2):
        return
 
    # If the first tree is exhausted
    # simply print the inorder
    # traversal of the second tree
    if (not root1):
        inorder(root2)
        return
 
    # If second tree is exhausted
    # simply print the inoreder
    # traversal of the first tree
    if (not root2):
        inorder(root1)
        return
 
    # A temporary pointer currently
    # pointing to root of first tree
    temp1 = root1
 
    # previous pointer to store the
    # parent of temporary pointer
    prev1 = None
 
    # Traverse through the first tree
    # until you reach the leftmost
    # element, which is the first element
    # of the tree in the inorder traversal.
    # This is the least element of the tree
    while (temp1.left):
        prev1 = temp1
        temp1 = temp1.left
 
    # Another temporary pointer currently
    # pointing to root of second tree
    temp2 = root2
 
    # Previous pointer to store the
    # parent of second temporary pointer
    prev2 = None
 
    # Traverse through the second tree
    # until you reach the leftmost element,
    # which is the first element of the
    # tree in inorder traversal. This is
    # the least element of the tree.
    while (temp2.left):
        prev2 = temp2
        temp2 = temp2.left
 
    # Compare the least current least
    # elements of both the tree
    if (temp1.data <= temp2.data):
 
        # If first tree's element is
        # smaller print it
        print(temp1.data, end = " ")
 
        # If the node has no parent, that
        # means this node is the root
        if (prev1 == None):
 
            # Simply make the right
            # child of the root as new root
            merge(root1.right, root2)
 
        # If node has a parent
        else:
 
            # As this node is the leftmost node,
            # it is certain that it will not have
            # a let child so we simply assign this
            # node's right pointer, which can be
            # either null or not, to its parent's left
            # pointer. This statement is
            # just doing the task of deleting the node
            prev1.left = temp1.right
 
            # recursively call the merge
            # function with updated tree
            merge(root1, root2)
    else:
 
        print(temp2.data, end = " ")
 
        # If the node has no parent, that
        # means this node is the root
        if (prev2 == None):
 
            # Simply make the right child
            # of root as new root
            merge(root1, root2.right)
 
        # If node has a parent
        else:
            prev2.left = temp2.right
 
            # Recursively call the merge
            # function with updated tree
            merge(root1, root2)
 
# Driver Code
if __name__ == '__main__':
 
    root1 = None
    root2 = None
    root1 = node(3)
    root1.left = node(1)
    root1.right = node(5)
    root2 = node(4)
    root2.left = node(2)
    root2.right = node(6)
 
    # Print sorted nodes of both trees
    merge(root1, root2)
 
# This code is contributed by mohit kumar 29


C#
// C# implementation of above approach
using System;
 
// Structure of a BST Node
public class Node
{
    public int data;
    public Node left, right;
     
    public Node(int item)
    {
        data = item;
        left = right = null;
    }
}
 
class GFG{
     
static Node root1;
static Node root2;
 
// A utility function to print
// Inorder traversal of a Binary Tree
static void inorder(Node root)
{
    if (root != null)
    {
        inorder(root.left);
        Console.WriteLine(root.data + " ");
        inorder(root.right);
    }
}
 
// The function to print data
// of two BSTs in sorted order
static void merge(Node root1, Node root2)
{
     
    // Base cases
    if (root1 == null && root2 == null)
    {
        return;
    }
     
    // If the first tree is exhausted
    // simply print the inorder traversal
    // of the second tree
    if (root1 == null)
    { 
        inorder(root2);
        return;
    }
     
    // If second tree is exhausted
    // simply print the inoreder
    // traversal of the first tree
    if (root2 == null)
    {
        inorder(root1);
        return;
    }
     
    // A temporary pointer currently
    // pointing to root of first tree
    Node temp1 = root1;
     
    // previous pointer to store the
    // parent of temporary pointer
    Node prev1 = null;
     
    // Traverse through the first tree
    // until you reach the leftmost element,
    // which is the first element of the tree
    // in the inorder traversal.
    // This is the least element of the tree
    while (temp1.left != null)
    {
        prev1 = temp1;
        temp1 = temp1.left;
    }
     
    // Another temporary pointer currently
    // pointing to root of second tree
    Node temp2 = root2;
     
    // Previous pointer to store the
    // parent of second temporary pointer
    Node prev2 = null;
     
    // Traverse through the second tree until
    // you reach the leftmost element, which
    // is the first element of the tree in
    // inorder traversal. This is the least
    // element of the tree.
    while (temp2.left != null)
    {
        prev2 = temp2;
        temp2 = temp2.left;
    }
     
    // Compare the least current least
    // elements of both the tree
    if (temp1.data <= temp2.data)
    {
         
        // If first tree's element is
        // smaller print it
        Console.Write(temp1.data + " ");
         
        // If the node has no parent, that
        // means this node is the root
        if (prev1 == null)
        {
             
            // Simply make the right
            // child of the root as new root
            merge(root1.right, root2);
        }
         
        // If node has a parent
        else
        {
             
            // As this node is the leftmost node,
            // it is certain that it will not have
            // a let child so we simply assign this
            // node's right pointer, which can be
            // either null or not, to its parent's
            // left pointer. This statement is just
            // doing the task of deleting the node
            prev1.left = temp1.right;
             
            // Recursively call the merge
            // function with updated tree
            merge(root1, root2);
        }
    }
    else
    {
        Console.Write(temp2.data + " ");
         
        // If the node has no parent, that
        // means this node is the root
        if (prev2 == null)
        {
             
            // Simply make the right child
            // of root as new root
            merge(root1, root2.right);
        }
         
        // If node has a parent
        else
        {
            prev2.left = temp2.right;
             
            // Recursively call the merge
            // function with updated tree
            merge(root1, root2);
        }
    }
}
 
// Driver Code
static public void Main()
{
    GFG.root1 = new Node(3);
    GFG.root1.left = new Node(1);
    GFG.root1.right = new Node(5);
     
    GFG.root2 = new Node(4);
    GFG.root2.left = new Node(2);
    GFG.root2.right = new Node(6);
     
    // Print sorted nodes of both trees
    merge(root1, root2);
}
}
 
// This code is contributed by avanitrachhadiya2155


输出:
1 2 3 4 5 6

时间复杂度: O((M + N)(h1 + h2)),其中M和N是两棵树的节点数,h1和h2分别是树的高度。
辅助空间: O(1)