Рекурсивное сравнение двух бинарных поисковых деревьев

1

Мне нужно сравнить два двоичных дерева поиска и посмотреть, равны они или нет. Я разработал следующий код, который использует рекурсию.

private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
    if(n1.getNodeData() != n2.getNodeData())
        return false;
    else
    {
        if(n1.left != null && n2.left != null)
            compareTrees(n1.left, n2.left);

        if(n1.right != null && n2.right != null)
            compareTrees(n1.right, n2.right);   
    }

    return true;
}

Проблема в том, что если два узла не равны, метод вернет false, но поскольку я использую рекурсию, возвращаемое значение будет переопределено до значения true, несмотря ни на что. Я застрял в этой проблеме весь день, и для меня ничего не работало. Я искал в Интернете, но я не нашел ничего, что имело бы отношение к моему коду. Есть ли способ обойти все вложенные методы и вернуть значение первому методу?

  • 3
    Вы забыли ключевое слово return когда вызываете compareTrees рекурсивно.
Теги:
recursion
binary-search-tree

4 ответа

4
Лучший ответ

Вам нужно вернуть результат сравнения поддерева:

boolean b1, b2;

if(n1.left != null && n2.left != null)
    b1 = compareTrees(n1.left, n2.left);

if(n1.right != null && n2.right != null)
    b2 = compareTrees(n1.right, n2.right);

return b1 && b2;

Но почему бы просто не иметь дело с null преимуществом?

private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
    if (n1 == null || n2 == null)
        return n1 == n2;  // i.e. both null

    if (n1.getNodeData() != n2.getNodeData())
        return false;

    return compareTrees(n1.left, n2.left) && compareTrees(n1.right, n2.right);
}
  • 0
    Лучше ответ, чем мой
  • 0
    Для всех, кто интересуется, это сравнение предварительного заказа, которое возвращает true, если и структура, и значения BST одинаковы, что, по-видимому, и было тем, о чем спрашивал OP
0

Попытайтесь столкнуться с проблемой, избегая нулевых значений и используя метод equals() вместо == сравнения для ваших узлов. Я так делаю так:

private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2){

//avoid nulls :TDD
if (n1==null && n1==n2) 
    return true;
if ((n1==null && n2!=null) || (n2==null && n1!=null)) 
    return false;

//ensure logic without nulls, comparing with equals() method
boolean areEquals =  n1.getNodeData().equals(n2.getNodeData());

//compare left
areEquals = areEquals && compareTrees(n1.left, n2.left);
//if still equals, compare right
if(areEquals) areEquals = areEquals && compareTrees(n1.right, n2.right);  

return areEquals;

}

0

Эффективно ваш код может уменьшиться до:

private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
       if(n1==null || n2==null) return n1==n2;
       return (n1.getNodeData()==n2.getNodeDate()) && compareTrees(n1.left, n2.left) && compareTrees(n1.right, n2.right) 
}

Я расскажу вам пару проблем с вашим кодом.

  1. Критерии завершения, когда корень равен нулю (это всегда произойдет в конце).

  2. Операторы возврата в рекурсивных вызовах. Вы всегда возвращаете истину в конце.

PS: Если вы добавляете NULL-проверки (объясняется в 1), вам не нужно добавлять нулевые проверки в последующие рекурсивные вызовы. Теперь вторая половина кода будет выглядеть так:

return compareTrees(n1.left, n2.left) && compareTrees(n1.right, n2.right);
0

Я бы сделал это, изменив порядок:

private boolean compareTrees(BinaryTreeNode n1, BinaryTreeNode n2)
{
    boolean equalLeft = false;
    boolean equalRight = false;

    if(n1.getNodeData() == n2.getNodeData())
    {
        if(n1.left != null && n2.left != null){
            equalLeft = compareTrees(n1.left, n2.left);
        } else{
            equalLeft = true;
        }

        if(n1.right != null && n2.right != null){
            equalRight = compareTrees(n1.right, n2.right);
        } else{
            equalRight = true;
        }

        return equalLeft && equalRight;

    } else{

         return false;
    }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню