检查两个二叉搜索树是否具有相同的有序遍历

时间:2014-02-24 22:04:37

标签: arrays algorithm tree

检查两个二叉搜索树是否具有相同的有序遍历。我天真的方法是按顺序遍历给定的两棵树并将每个元素分别复制到一个数组上,然后检查这两个数组是否相同。但我觉得我们应该只能将一个树中的元素复制到一个数组上,然后使用该数组来动态验证另一个树,而不是使用两个数组。或者更好的是,可能有一种方法可以在不使用任何数组的情况下完成。我的代码如下,不确定我的hasSameInOrder()实现是否正确。或者我们可以不使用任何阵列吗? 请注意,具有相同有序遍历的两棵树意味着如果在按顺序遍历时将元素复制到数组中,则两个结果数组应具有相同的值。因此,它们不一定具有相同的结构,以便进行相同的有序遍历。

public boolean checkTwoBSTHaveSameInOrder(Node n1, Node n2) {
   LinkedList<Node> queue = new LinkedList<Node>();
   inOrder(n1, buffer);
   hasSameInOrder(n2, queue)
   return queue==null? false: true;
}
public void inOrder(Node node, LinkedList<Node> queue) {
   if (node==null)
       return;
   inOrder(node.left, queue);
   queue.add(node);
   inOrder(node.right, queue);
}
public void hasSameInOrder(Node node, LinkedList<Node> queue) {
   if (node==null)
      return;
   hasSameInOrder(n2.left, queue));
   if (queue==null)
      return;
   else {
      if (node!=queue.poll())
           queue=null;
   }
   hasSameInOrder(n2.right, queue));
} 

6 个答案:

答案 0 :(得分:1)

在两个树的Inorder Traversal的迭代实现中使用单个循环。您将需要两个添加的堆栈(读取队列)来跟踪匹配。显然,这不会改善最坏情况的渐近时间,这是不可能更好的,但是现有方法确保了随机树对的合理时间增益。

答案 1 :(得分:0)

您可以按以下方式使用单个数组: -

int count =0;
int[] arr;

void inorder(node*p) {

  if(p!=null) {

       inorder(p->left);
       arr[count++] = p->data;
       inorder(p->right);
  }  

}

int c2 =0;
boolean checkSame(node*p,int[] arr) {

    if(p!=null) {
       boolean t = true;  
       t = checkSame(p->left,arr);
       if(c2+1>=count||arr[c2++]!=p->data) {

           return(false);  
       } 
       return(t&&checkSame(p->right,arr));

    }

}

答案 2 :(得分:0)

如果我们可以重组树,然后将树转移到左或右倾斜格式,然后在单个遍历中进行比较Skewed Tree

另外,我们可以通过仅将一棵树转换为倾斜格式来避免成本,并在对其他树进行顺序遍历时进行比较。

答案 3 :(得分:0)

是的,有一种方法可以在不使用数组的情况下完成。我们可以使用Threads来实现它。我们可以使用wait()和notify()在线程之间进行交互。在单独的线程中触发两个树中的递归顺序遍历。读取一棵树中的第一个元素,并等待其他树读取其第一个元素。比较这些元素并继续进行其余元素。您可以按照以下示例代码进行操作。

//common lock for both threads
Object lock = new Object();

// flag to check if traverseFirstTree can come out of wait or not
boolean proceedFirst = false;

// flag to check if traverseSecondTree can come out of wait or not
boolean proceedSecond = false;

//value of current element in second BinarySearchTree
int element;

boolean identicalInorderOrNot(BST bst1, BST bst2){
  //check if no. of elements in both are same. If not return false
  if (bst1.size() != bst2.size()){
    return false;
  } 
  Thread thread = new Thread (new Runnable(){
    void run(){
      traverseSecondTree(bst2);
    }
  });
  //it does not matter if traverseSecondTree gets executed before traverseFirstTree(), as we have check for this condition
  thread.start()
  return traverseFirstTree(bst1);
}

private boolean traverseFirstTree(BST node){
  if(bst1 == null){
    return true;
  }
  if (!traverseFirstTree(node.left)){
    return false;
  }
  synchronized(lock){
    proceedFirst = false;
    while (!proceedFirst){
      proceedSecond = true;
      wait();
    }
  notify()
  }
  //check if root data of bst1 is same as current element of bst2
  if (node.data != element){
    return false;
  }
  return traverseFirstTree(node.right)
}

private void traverseSecondTree(BST node){
  if (node ==  null){
    return true;
  }
  traverseSecondTree(node.left)
  synchronized(lock){
    while (!proceedSecond){
      wait();
    }
    element = node.data;
    proceedFirst = true;
    proceedSecond = false;
    notify();

  traverseSecondTree(node.right)
}

答案 4 :(得分:0)

我们可以在更好的空间复杂度O(1)中做到这一点 我们可以使用Morris Traversal遍历树,然后逐个元素比较值。

对于以下实现,我假设两个树都具有相同数量的节点。

  bool isSame(root1, root2){
    while(root1!=null && root2!=null){
        while(root1->left!=NULL){
            auto maxleft = getmaxnode(root1->left);
            maxleft->right = root1;
            auto next = root1->left;
            root1->left = NULL;
            root1 = next;
        }
        while(root2->left!=NULL){
            auto maxleft = getmaxnode(root2->left);
            maxleft->right = root2;
            auto next = root2->left;
            root2->left = NULL;
            root2 = next;
        }
        if(root1->val != root2->val) return false;
    }
    return true;
}

答案 5 :(得分:0)

有两棵树,其顺序与以下相同

  1. InOrder函数tree1将填充队列
  2. CheckInOrder函数会将值与第二棵树进行比较
  3. 如果存在不匹配,则返回false
    /*
      Tree 1           Tree 2
         5                3
        / \              / \
       3   7            1   6
      /   /                / \
     1   6                5   7
    [1,3,5,6,7]      [1,3,5,6,7]
    */
    
    #include <iostream>
    #include <queue>
    
    using namespace std;
    
    struct NODE {
        NODE() {
            val = 0;
            left = NULL;
            right = NULL;
        }
    
        NODE(int n) {
            val = n;
            left = NULL;
            right = NULL;
        }
        int val;
        NODE* left;
        NODE* right;
    };
    
    void InOrder(NODE* root, queue<int>& q)
    {
        if (root == NULL)
            return;

        InOrder(root->left, q);
        q.push(root->val);
        InOrder(root->right, q);
    }
        
    bool CheckInOrder(NODE* root, queue<int>& q)
    {
        if (root == NULL)
            return true;
        if (!CheckInOrder(root->left, q))
            return false;
        if (!q.empty() && root->val == q.front())
            q.pop();
        else
            return false;
    
        return CheckInOrder(root->right, q);
    }
    
    int main()
    {
        NODE* tree1;
        NODE* tree2;
        queue<int> tq;
    
        tree1 = new NODE(5);
        tree1->left = new NODE(3);
        tree1->right = new NODE(7);
        tree1->left->left = new NODE(1);
        tree1->right->left = new NODE(6);
    
        tree2 = new NODE(3);
        tree2->left = new NODE(1);
        tree2->right = new NODE(6);
        tree2->right->left = new NODE(5);
        tree2->right->right = new NODE(7);
    
        InOrder(tree1, tq);
        if (CheckInOrder(tree2, tq) && tq.empty())
            cout << "TRUE";
        else
            cout << "FALSE";
    }