Мне нужно сравнить два двоичных дерева поиска и посмотреть, равны они или нет. Я разработал следующий код, который использует рекурсию.
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, несмотря ни на что. Я застрял в этой проблеме весь день, и для меня ничего не работало. Я искал в Интернете, но я не нашел ничего, что имело бы отношение к моему коду. Есть ли способ обойти все вложенные методы и вернуть значение первому методу?
Вам нужно вернуть результат сравнения поддерева:
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);
}
Попытайтесь столкнуться с проблемой, избегая нулевых значений и используя метод 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;
}
Эффективно ваш код может уменьшиться до:
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)
}
Я расскажу вам пару проблем с вашим кодом.
Критерии завершения, когда корень равен нулю (это всегда произойдет в конце).
Операторы возврата в рекурсивных вызовах. Вы всегда возвращаете истину в конце.
PS: Если вы добавляете NULL-проверки (объясняется в 1), вам не нужно добавлять нулевые проверки в последующие рекурсивные вызовы. Теперь вторая половина кода будет выглядеть так:
return compareTrees(n1.left, n2.left) && compareTrees(n1.right, n2.right);
Я бы сделал это, изменив порядок:
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;
}
}
return
когда вызываетеcompareTrees
рекурсивно.