簡體   English   中英

檢查兩個二叉搜索樹是否具有相同的中序遍歷

[英]Check two binary search trees have the same in-order traversal

檢查兩個二叉搜索樹是否具有相同的中序遍歷。 我天真的方法是按順序遍歷給定的兩棵樹,並將每個元素分別復制到一個數組中,然后檢查這兩個數組是否相同。 但是我覺得我們應該能夠將一棵樹中的元素復制到一個數組中,然后使用該數組來動態驗證另一棵樹,而不是使用兩個數組。 或者更好的是,可能有一種方法可以在不使用任何數組的情況下做到這一點。 我的代碼如下,不確定我對 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));
} 

在兩個樹的中序遍歷的迭代實現中使用單個循環。您將需要添加兩個堆棧(讀取隊列)來跟蹤匹配。 顯然,這不會改善不可能更好的最壞情況漸近時間,但現有方法確保在隨機一對樹上獲得合理的時間增益。

您可以按以下方式使用單個數組:-

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));

    }

}

如果我們可以重構樹,那么將兩棵樹都轉換為左偏或右偏的格式,然后在單個遍歷偏斜樹中進行比較

否則,我們可以通過僅將一棵樹轉換為傾斜格式並在對其他樹進行中序遍歷的同時進行比較來避免成本。

是的,有一種方法可以在不使用數組的情況下做到這一點。 我們可以使用線程來實現它。 我們可以使用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)
}

我們可以在更好的空間復雜度 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;
}

有兩棵樹,它們的順序如下

  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";
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM