用递归评估二叉树
Posted
技术标签:
【中文标题】用递归评估二叉树【英文标题】:Evaluating binary tree with recursion 【发布时间】:2020-07-10 10:57:49 【问题描述】:我有一个二叉树,在外部节点中包含整数,在内部节点中包含运算符。 我将树的根节点发送到我的评估树方法。 我想遍历树并计算最终结果。 节点类的字段是
private Node left;
private Node right;
char value;
例如,我想计算 (2+5)/8-(21+3) 应该等于,四舍五入,到 -23。 当我尝试这样做时,我得到 -5 的结果。与舍入无关,当我尝试计算 21+3 时,我得到的结果为 5。任何指导将不胜感激。
int evaluateTree(Node node)
System.out.println("Inside evaluateTree");
if (Character.isDigit(node.value))
return Character.getNumericValue(node.value);
else
int operand1 = evaluateTree(node.left);
int operand2 = evaluateTree(node.right);
switch (node.value)
case '+':
return (int) Math.round(operand1 + operand2);
case '-':
return (int) Math.round(operand1 - operand2);
case '*':
return (int) Math.round(operand1 * operand2);
case '/':
return (int) Math.round(operand1 / operand2);
default:
throw new IllegalStateException("Unexpected value: " + node.value);
这就是我创建树的方式
public void createTree()
Scanner keyboardInput = new Scanner(System.in);
ArrayList<String> postFixArray = new ArrayList<>();
postFixArray = getPostFixString("(21+3)");
System.out.println("\nCREATE TREE PRINTING\n");
System.out.println(postFixArray);
Stack<Node> nodeStack = new Stack<>();
while (!postFixArray.isEmpty())
String temp = postFixArray.get(0);
char charTemp = temp.charAt(0);
if (!isOperator(charTemp))
if (!Character.isDigit(charTemp))
System.out.println("Enter the integer value for your variable " + charTemp + ": ");
int setVarValue = keyboardInput.nextInt();
for (int i = 0; i < postFixArray.size(); i++)
if (charTemp == postFixArray.get(i).charAt(0))
postFixArray.set(i, String.valueOf(setVarValue));
String tempLink = postFixArray.remove(0);
char nodeData = tempLink.charAt(0);
Node leaf = new Node(nodeData);
nodeStack.push(leaf);
else
if (nodeStack.size() >= 1)
String tempLink = postFixArray.remove(0);
char nodeData = tempLink.charAt(0);
Node leaf = new Node(nodeData);
leaf.right = nodeStack.pop();
leaf.left = nodeStack.pop();
nodeStack.push(leaf);
Node root = nodeStack.pop();
System.out.println(root);
System.out.println(evaluateTree(root));
【问题讨论】:
对于哪个例子它不起作用。我试过 2+5,效果很好。 是的,就像@PrernaGupta 说的那样,无论您没有打印返回值还是您的树结构不正确,它都能正常工作。 是的,老实说我忘了打印返回值。但是在意识到这个错误之后,我确实改变了这个问题。 您上面提到的示例 ((2+5)/7-(21+3)) 是否在上述代码中工作。因为在您的节点中,您将 value 作为 char ,但 21 不是 char 值,它会给出错误。 @PrernaGupta 有什么办法呢? 【参考方案1】:为了对返回的值进行四舍五入,可以将evaluateTree
的返回类型更改为Double
,然后使用Math.round对值进行四舍五入,这将返回一个int值。
这里是函数evaluateTree
的更新代码:
public static Double evaluateTree(Node node)
System.out.println("Inside evaluateTree");
if (Character.isDigit(node.value))
return (double)Character.getNumericValue(node.value);
else
double operand1 = evaluateTree(node.left);
double operand2 = evaluateTree(node.right);
switch (node.value)
case '+':
return operand1 + operand2;
case '-':
return operand1 - operand2;
case '*':
return operand1 * operand2;
case '/':
return operand1 / operand2;
default:
throw new IllegalStateException("Unexpected value: " + node.value);
最后,无论你在哪里调用这个方法,你都可以将它的值返回为
Math.round(evaluateTree(root))
【讨论】:
谢谢。但是,与舍入无关,当我尝试计算 21+3 时,我得到的结果为 5。 您能否分享您如何为上述表达式创建节点的代码,因为我不确定您如何将 21 添加到节点值字段中,因为它是 char。 我假设您以任何方式向 Node 中的 value 字段添加值,它只占用第一个字符。您提到的 (2+5)/8-(21+3) 的示例结果是 -5,因为从 21 开始它只需要 2 。因此,它转移到 (2+5)/8-(2+3) => 7/8 - 5 =>0 -5 =-5 。 21+3 => 2+3 =5 也是如此。这只是我的假设。一旦您粘贴代码以显示您如何创建此类表达式的节点,我们可以验证相同 刚看到你的代码。为了创建叶节点,您通过执行 String tempLink = postFixArray.remove(0); 来计算叶节点的值;字符节点数据 = tempLink.charAt(0);.现在假设 postFixArray.charAt(0) 的值为 24,然后您正在执行 "24".charAt(0),结果为 2,并且您的叶节点的创建值为 2 而不是 24。所以,与我提到的相同在我上面的评论中,您正在通过提取 string 的第一个 char 值来创建 digit 节点,而不是使用整个字符串,因为它适用于 0-9 ,但之后只使用第一个字符..【参考方案2】:四舍五入
要对值进行舍入,只需在 switch 语句的返回值中添加一个舍入函数。您应该将其转换为 double
或 float
的除法,因为如果您不这样做,它将被四舍五入。
switch (node.value)
case '+':
return round(operand1 + operand2);
case '-':
return round(operand1 - operand2);
case '*':
return round(operand1 * operand2);
case '/':
return round((float) operand1 / operand2);
default:
throw new IllegalStateException("Unexpected value: " + node.value);
-
public static int round(double x)
return (int) Math.round(x);
为了验证是否存在多于一位的整数,您可能应该使用正则表达式,但这个问题应该有自己的专门问题。
编辑: 我创建了一些没有树创建方法 的测试用例来测试这 段代码是否正常工作。它通过了以下测试:
// 21/3 = 7
public static void testCaseOne()
Node three = new Node(null, null, '3');
Node nine = new Node(null, null, '9');
Node nine2 = new Node(null, null, '9');
Node three2 = new Node(null, null, '3');
Node plus3 = new Node(nine, three, '+');
Node plus2 = new Node(nine2, plus3, '+');
Node plus = new Node(plus2, three2, '/');
System.out.println("PASSED: " + (evaluateTree(plus) == 7) + " " + evaluateTree(plus));
// 21+3 = 24
public static void testCaseTwo()
Node three = new Node(null, null, '3');
Node nine = new Node(null, null, '9');
Node nine2 = new Node(null, null, '9');
Node three2 = new Node(null, null, '3');
Node plus3 = new Node(nine, three, '+');
Node plus2 = new Node(nine2, plus3, '+');
Node plus = new Node(plus2, three2, '+');
System.out.println("PASSED: " + (evaluateTree(plus) == 24) + " " + evaluateTree(plus));
// 9/9/3/3 = 1
public static void testCaseThree()
Node three = new Node(null, null, '3');
Node nine = new Node(null, null, '9');
Node nine2 = new Node(null, null, '9');
Node three2 = new Node(null, null, '3');
Node plus3 = new Node(nine, three, '/');
Node plus2 = new Node(nine2, plus3, '/');
Node plus = new Node(plus2, three2, '/');
System.out.println("PASSED: " + (evaluateTree(plus) == 1) + " " + evaluateTree(plus));
// 21/2 = 10.5 = 11
public static void testCaseFour()
Node three = new Node(null, null, '3');
Node nine = new Node(null, null, '9');
Node nine2 = new Node(null, null, '9');
Node two = new Node(null, null, '2');
Node plus3 = new Node(nine, three, '+');
Node plus2 = new Node(nine2, plus3, '+');
Node plus = new Node(plus2, two, '/');
System.out.println("PASSED: " + (evaluateTree(plus) == 11) + " " + evaluateTree(plus));
// 22/3 = 7.33 = 7
public static void testCaseFive()
Node four = new Node(null, null, '4');
Node nine = new Node(null, null, '9');
Node nine2 = new Node(null, null, '9');
Node three2 = new Node(null, null, '3');
Node plus3 = new Node(nine, four, '+');
Node plus2 = new Node(nine2, plus3, '+');
Node plus = new Node(plus2, three2, '/');
System.out.println("PASSED: " + (evaluateTree(plus) == 7) + " " + evaluateTree(plus));
验证
要进一步添加验证输入,您可以执行以下操作:
String regexExpression = "([()\\-+/0-9]+)?\\d2([()\\-+/0-9]+)?";
String str = "(2+5)/8-(21+3)";
boolean containsLongInts = str.matches(regexExpression);
System.out.println(str + " contains long ints: " + containsLongInts);
String str2 = "(2+5)/8-(2+3)";
boolean containsLongInts2 = str2.matches(regexExpression);
System.out.println(str2 + " contains long ints: " + containsLongInts2);
【讨论】:
以上是关于用递归评估二叉树的主要内容,如果未能解决你的问题,请参考以下文章