📌  相关文章
📜  在两个二叉搜索树中打印公共节点

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

给定两个Binary Search Trees,在其中找到公共节点。换句话说,找到两个BST的交集。

例子:
树

方法1(简单解决方案)一种简单的方法是一次搜索第二棵树中第一棵树的每个节点。该解决方案的时间复杂度为O(m * h),其中m是第一棵树中的节点数,h是第二棵树的高度。

方法2

  • 方法–如果我们想到另一个给我们两个排序数组并必须找到它们之间的交集的问题,则可以使用两个指针技术轻松地做到这一点。现在,我们可以轻松地将此问题转换为上述问题。我们知道,如果我们将BST的有序遍历存储在数组中,则该数组将以升序排序。因此,我们可以做的就是简单地对两棵树进行有序遍历,并将它们存储在两个单独的数组中,然后找到两个数组之间的交集。
  • 算法 –
    1)对第一棵树进行有序遍历,并将遍历存储在辅助数组ar1 []中。请参阅此处的sortedInorder()。
    2)对第二棵树进行有序遍历,并将遍历存储在辅助数组ar2 []中
    3)找到ar1 []和ar2 []的交集。有关详细信息,请参见此。
  • 复杂度分析:
    • 时间复杂度: O(m + n)。
      这里的“ m”和“ n”分别是第一棵树和第二棵树中的节点数,因为我们需要遍历两棵树。
    • 辅助空间:不使用任何数据结构来存储值-:O(m + n)
      原因是我们需要两个单独的数组来存储两个树的有序遍历。

    方法3(线性时间和有限的额外空间)
    这个想法是使用迭代有序遍历

  • 方法:
    这里的想法是优化空间。在上述方法中,我们存储树的所有元素,然后进行比较,但问题是确实需要存储所有元素。一个人可以做的是存储树的特定分支(最坏的情况是“树的高度”),然后开始比较。我们可以采用两个堆栈并将树的有序遍历存储在各个堆栈中,但是元素的最大数量应等于树的特定分支。该分支结束后,我们便开始弹出并比较堆栈中的元素。现在,如果top(stack-1)在top(stack-1)的右分支中可以有更多元素,这些元素大于它,并且可以等于top(stack-2)。因此,我们插入top(stack-1)的右分支,直到它等于NULL。在每次这样的插入结束时,我们要检查三个条件,然后相应地在堆栈中进行插入。
    if top(stack-1)right (then do insertions)
    
    if top(stack-1)>top(stack-2)
    root2=root2->right (then do insertions)
    
    else
    It's a match
    
    C++
    // C++ program of iterative traversal based method to
    // find common elements in two BSTs.
    #include
    #include
    using namespace std;
      
    // A BST node
    struct Node
    {
        int key;
        struct Node *left, *right;
    };
      
    // A utility function to create a new node
    Node *newNode(int ele)
    {
        Node *temp = new Node;
        temp->key = ele;
        temp->left = temp->right = NULL;
        return temp;
    }
      
    // Function two print common elements in given two trees
    void printCommon(Node *root1, Node *root2)
    {
        // Create two stacks for two inorder traversals
        stack stack1, s1, s2;
      
        while (1)
        {
            // push the Nodes of first tree in stack s1
            if (root1)
            {
                s1.push(root1);
                root1 = root1->left;
            }
      
            // push the Nodes of second tree in stack s2
            else if (root2)
            {
                s2.push(root2);
                root2 = root2->left;
            }
      
            // Both root1 and root2 are NULL here
            else if (!s1.empty() && !s2.empty())
            {
                root1 = s1.top();
                root2 = s2.top();
      
                // If current keys in two trees are same
                if (root1->key == root2->key)
                {
                    cout << root1->key << " ";
                    s1.pop();
                    s2.pop();
      
                    // move to the inorder successor
                    root1 = root1->right;
                    root2 = root2->right;
                }
      
                else if (root1->key < root2->key)
                {
                    // If Node of first tree is smaller, than that of
                    // second tree, then its obvious that the inorder
                    // successors of current Node can have same value
                    // as that of the second tree Node. Thus, we pop
                    // from s2
                    s1.pop();
                    root1 = root1->right;
      
                    // root2 is set to NULL, because we need
                    // new Nodes of tree 1
                    root2 = NULL;
                }
                else if (root1->key > root2->key)
                {
                    s2.pop();
                    root2 = root2->right;
                    root1 = NULL;
                }
            }
      
            // Both roots and both stacks are empty
            else  break;
        }
    }
      
    // A utility function to do inorder traversal
    void inorder(struct Node *root)
    {
        if (root)
        {
            inorder(root->left);
            cout<key<<" ";
            inorder(root->right);
        }
    }
      
    /* A utility function to insert a new Node with given key in BST */
    struct Node* insert(struct Node* node, int key)
    {
        /* If the tree is empty, return a new Node */
        if (node == NULL) return newNode(key);
      
        /* Otherwise, recur down the tree */
        if (key < node->key)
            node->left  = insert(node->left, key);
        else if (key > node->key)
            node->right = insert(node->right, key);
      
        /* return the (unchanged) Node pointer */
        return node;
    }
      
    // Driver program
    int main()
    {
        // Create first tree as shown in example
        Node *root1 = NULL;
        root1 = insert(root1, 5);
        root1 = insert(root1, 1);
        root1 = insert(root1, 10);
        root1 = insert(root1,  0);
        root1 = insert(root1,  4);
        root1 = insert(root1,  7);
        root1 = insert(root1,  9);
      
        // Create second tree as shown in example
        Node *root2 = NULL;
        root2 = insert(root2, 10);
        root2 = insert(root2, 7);
        root2 = insert(root2, 20);
        root2 = insert(root2, 4);
        root2 = insert(root2, 9);
      
        cout << "Tree 1 : ";
        inorder(root1);
        cout << endl;
      
        cout << "Tree 2 : ";
        inorder(root2);
      
        cout << "\nCommon Nodes: ";
        printCommon(root1, root2);
      
        return 0;
    }


    Java
    // Java program of iterative traversal based method to 
    // find common elements in two BSTs.
    import java.util.*;
    class GfG { 
      
    // A BST node 
    static class Node 
    { 
        int key; 
        Node left, right; 
    }
      
    // A utility function to create a new node 
    static Node newNode(int ele) 
    { 
        Node temp = new Node(); 
        temp.key = ele; 
        temp.left = null;
        temp.right = null; 
        return temp; 
    } 
      
    // Function two print common elements in given two trees 
    static void printCommon(Node root1, Node root2) 
    { 
          
        Stack s1 = new Stack (); 
        Stack s2 = new Stack ();
      
        while (true) 
        { 
            // push the Nodes of first tree in stack s1 
            if (root1 != null) 
            { 
                s1.push(root1); 
                root1 = root1.left; 
            } 
      
            // push the Nodes of second tree in stack s2 
            else if (root2 != null) 
            { 
                s2.push(root2); 
                root2 = root2.left; 
            } 
      
            // Both root1 and root2 are NULL here 
            else if (!s1.isEmpty() && !s2.isEmpty()) 
            { 
                root1 = s1.peek(); 
                root2 = s2.peek(); 
      
                // If current keys in two trees are same 
                if (root1.key == root2.key) 
                { 
                    System.out.print(root1.key + " "); 
                    s1.pop(); 
                    s2.pop(); 
      
                    // move to the inorder successor 
                    root1 = root1.right; 
                    root2 = root2.right; 
                } 
      
                else if (root1.key < root2.key) 
                { 
                    // If Node of first tree is smaller, than that of 
                    // second tree, then its obvious that the inorder 
                    // successors of current Node can have same value 
                    // as that of the second tree Node. Thus, we pop 
                    // from s2 
                    s1.pop(); 
                    root1 = root1.right; 
      
                    // root2 is set to NULL, because we need 
                    // new Nodes of tree 1 
                    root2 = null; 
                } 
                else if (root1.key > root2.key) 
                { 
                    s2.pop(); 
                    root2 = root2.right; 
                    root1 = null; 
                } 
            } 
      
            // Both roots and both stacks are empty 
            else break; 
        } 
    } 
      
    // A utility function to do inorder traversal 
    static void inorder(Node root) 
    { 
        if (root != null) 
        { 
            inorder(root.left); 
            System.out.print(root.key + " "); 
            inorder(root.right); 
        } 
    } 
      
    /* A utility function to insert a new Node with given key in BST */
    static Node insert(Node node, int key) 
    { 
        /* If the tree is empty, return a new Node */
        if (node == null) return newNode(key); 
      
        /* Otherwise, recur down the tree */
        if (key < node.key) 
            node.left = insert(node.left, key); 
        else if (key > node.key) 
            node.right = insert(node.right, key); 
      
        /* return the (unchanged) Node pointer */
        return node; 
    } 
      
    // Driver program 
    public static void main(String[] args) 
    { 
        // Create first tree as shown in example 
        Node root1 = null; 
        root1 = insert(root1, 5); 
        root1 = insert(root1, 1); 
        root1 = insert(root1, 10); 
        root1 = insert(root1, 0); 
        root1 = insert(root1, 4); 
        root1 = insert(root1, 7); 
        root1 = insert(root1, 9); 
      
        // Create second tree as shown in example 
        Node root2 = null; 
        root2 = insert(root2, 10); 
        root2 = insert(root2, 7); 
        root2 = insert(root2, 20); 
        root2 = insert(root2, 4); 
        root2 = insert(root2, 9); 
      
        System.out.print("Tree 1 : " + "\n"); 
        inorder(root1); 
        System.out.println();
        System.out.print("Tree 2 : " + "\n"); 
        inorder(root2); 
        System.out.println();
        System.out.println("Common Nodes: ");
      
        printCommon(root1, root2); 
      
    }
    }


    Python3
    # Python3 program of iterative traversal based 
    # method to find common elements in two BSTs. 
      
    # A utility function to create a new node 
    class newNode:
        def __init__(self, key):
            self.key = key
            self.left = self.right = None
      
    # Function two print common elements 
    # in given two trees 
    def printCommon(root1, root2):
          
        # Create two stacks for two inorder
        # traversals 
        s1 = []
        s2 = []
      
        while 1:
              
            # append the Nodes of first 
            # tree in stack s1 
            if root1:
                s1.append(root1)
                root1 = root1.left
      
            # append the Nodes of second tree
            # in stack s2 
            elif root2:
                s2.append(root2)
                root2 = root2.left
      
            # Both root1 and root2 are NULL here 
            elif len(s1) != 0 and len(s2) != 0:
                root1 = s1[-1] 
                root2 = s2[-1] 
      
                # If current keys in two trees are same 
                if root1.key == root2.key:
                    print(root1.key, end = " ")
                    s1.pop(-1) 
                    s2.pop(-1)
      
                    # move to the inorder successor 
                    root1 = root1.right 
                    root2 = root2.right
      
                elif root1.key < root2.key:
                      
                    # If Node of first tree is smaller, than 
                    # that of second tree, then its obvious 
                    # that the inorder successors of current 
                    # Node can have same value as that of the 
                    # second tree Node. Thus, we pop from s2 
                    s1.pop(-1)
                    root1 = root1.right 
      
                    # root2 is set to NULL, because we need 
                    # new Nodes of tree 1 
                    root2 = None
                elif root1.key > root2.key:
                    s2.pop(-1)
                    root2 = root2.right 
                    root1 = None
      
            # Both roots and both stacks are empty 
            else:
                break
      
    # A utility function to do inorder traversal 
    def inorder(root):
        if root:
            inorder(root.left) 
            print(root.key, end = " ")
            inorder(root.right)
      
    # A utility function to insert a new Node
    # with given key in BST 
    def insert(node, key):
          
        # If the tree is empty, return a new Node 
        if node == None:
            return newNode(key) 
      
        # Otherwise, recur down the tree 
        if key < node.key: 
            node.left = insert(node.left, key) 
        elif key > node.key: 
            node.right = insert(node.right, key)
              
        # return the (unchanged) Node pointer 
        return node
      
    # Driver Code 
    if __name__ == '__main__':
          
        # Create first tree as shown in example 
        root1 = None
        root1 = insert(root1, 5) 
        root1 = insert(root1, 1) 
        root1 = insert(root1, 10) 
        root1 = insert(root1, 0) 
        root1 = insert(root1, 4) 
        root1 = insert(root1, 7) 
        root1 = insert(root1, 9) 
      
        # Create second tree as shown in example 
        root2 = None
        root2 = insert(root2, 10) 
        root2 = insert(root2, 7) 
        root2 = insert(root2, 20) 
        root2 = insert(root2, 4) 
        root2 = insert(root2, 9)
      
        print("Tree 1 : ") 
        inorder(root1) 
        print()
          
        print("Tree 2 : ")
        inorder(root2)
        print()
      
        print("Common Nodes: ") 
        printCommon(root1, root2)
          
    # This code is contributed by PranchalK


    C#
    using System;
    using System.Collections.Generic;
      
    // C# program of iterative traversal based method to 
    // find common elements in two BSTs. 
    public class GfG
    {
      
    // A BST node 
    public class Node
    {
        public int key;
        public Node left, right;
    }
      
    // A utility function to create a new node 
    public static Node newNode(int ele)
    {
        Node temp = new Node();
        temp.key = ele;
        temp.left = null;
        temp.right = null;
        return temp;
    }
      
    // Function two print common elements in given two trees 
    public static void printCommon(Node root1, Node root2)
    {
        Stack s1 = new Stack ();
        Stack s2 = new Stack ();
      
        while (true)
        {
            // push the Nodes of first tree in stack s1 
            if (root1 != null)
            {
                s1.Push(root1);
                root1 = root1.left;
            }
      
            // push the Nodes of second tree in stack s2 
            else if (root2 != null)
            {
                s2.Push(root2);
                root2 = root2.left;
            }
      
            // Both root1 and root2 are NULL here 
            else if (s1.Count > 0 && s2.Count > 0)
            {
                root1 = s1.Peek();
                root2 = s2.Peek();
      
                // If current keys in two trees are same 
                if (root1.key == root2.key)
                {
                    Console.Write(root1.key + " ");
                    s1.Pop();
                    s2.Pop();
      
                    // move to the inorder successor 
                    root1 = root1.right;
                    root2 = root2.right;
                }
      
                else if (root1.key < root2.key)
                {
                    // If Node of first tree is smaller, than that of 
                    // second tree, then its obvious that the inorder 
                    // successors of current Node can have same value 
                    // as that of the second tree Node. Thus, we pop 
                    // from s2 
                    s1.Pop();
                    root1 = root1.right;
      
                    // root2 is set to NULL, because we need 
                    // new Nodes of tree 1 
                    root2 = null;
                }
                else if (root1.key > root2.key)
                {
                    s2.Pop();
                    root2 = root2.right;
                    root1 = null;
                }
            }
      
            // Both roots and both stacks are empty 
            else
            {
                break;
            }
        }
    }
      
    // A utility function to do inorder traversal 
    public static void inorder(Node root)
    {
        if (root != null)
        {
            inorder(root.left);
            Console.Write(root.key + " ");
            inorder(root.right);
        }
    }
      
    /* A utility function to insert a new Node with given key in BST */
    public static Node insert(Node node, int key)
    {
        /* If the tree is empty, return a new Node */
        if (node == null)
        {
            return newNode(key);
        }
      
        /* Otherwise, recur down the tree */
        if (key < node.key)
        {
            node.left = insert(node.left, key);
        }
        else if (key > node.key)
        {
            node.right = insert(node.right, key);
        }
      
        /* return the (unchanged) Node pointer */
        return node;
    }
      
    // Driver program 
    public static void Main(string[] args)
    {
        // Create first tree as shown in example 
        Node root1 = null;
        root1 = insert(root1, 5);
        root1 = insert(root1, 1);
        root1 = insert(root1, 10);
        root1 = insert(root1, 0);
        root1 = insert(root1, 4);
        root1 = insert(root1, 7);
        root1 = insert(root1, 9);
      
        // Create second tree as shown in example 
        Node root2 = null;
        root2 = insert(root2, 10);
        root2 = insert(root2, 7);
        root2 = insert(root2, 20);
        root2 = insert(root2, 4);
        root2 = insert(root2, 9);
      
        Console.Write("Tree 1 : " + "\n"); 
        inorder(root1); 
        Console.WriteLine(); 
        Console.Write("Tree 2 : " + "\n"); 
        inorder(root2); 
        Console.WriteLine(); 
        Console.Write("Common Nodes: " + "\n"); 
      
        printCommon(root1, root2);
      
    }
    }
      
    // This code is contributed by Shrikant13


    输出:

    4 7 9 10
  • 复杂度分析:
    • 时间复杂度: O(n + m)。
      这里的“ m”和“ n”分别是第一棵树和第二棵树中的节点数,因为我们需要遍历两棵树。
    • 辅助空间:使用堆栈存储值,最多元素=’树的高度’:O(h1 + h2)