繁体   English   中英

二元表达式树将后缀转换为中缀,反之亦然

[英]Binary expression tree converting postfix to infix and vice versa

任务 在此项目中,您需要开发一个二叉表达式树,并使用该树将后缀表达式和中缀表达式相互转换。 一个表达式可以包含 4 种运算符:乘法 (*)、除法 (/)、加号 (+) 和减号 (-)。 我们假设乘法和除法的优先级相同,加减法的优先级相同,乘除法的优先级高于加减法。 所有运算符都是左关联的(即从左到右关联)。 此外,表达式可能包含数字 (1, 129, ...) 或字母标识符 (a, x, var, ...) 形式的操作数。 二元表达式树:构建一个名为“BET”的二元表达式树类。 您的 BET 类必须有一个名为“BinaryNode”的嵌套类来包含与节点相关的信息(例如,包括元素和指向子节点和父节点的指针)。 您可以为 BinaryNode 的元素字段选择任何类型。 此外,BET至少必须支持以下接口功能:

公共接口:

BET() -- 默认零参数构造函数。 建立一棵空树。

BET(String expr, char mode) -- 两个参数的构造函数,其中参数“mode”指定“expr”是否是包含后缀或中缀表达式的字符串。 “mode”的可能值是后缀的“p”和中缀表达式的“i”。 树应该基于表达式构建。 表达式中的标记用空格分隔。 理想情况下,这应该通过调用 buildFromPostfix 或 buildFromInfix 来完成。 如果构建树失败,则抛出 IllegalStateException。

bool buildFromPostfix(String postfix) -- 参数“postfix”是一个包含后缀表达式的字符串。 树应该基于后缀表达式构建。 后缀表达式中的标记用空格分隔。 如果在调用函数之前树中包含节点,则需要先删除现有节点。 如果新树构建成功,则返回 true。 如果遇到错误,则返回 false。

bool buildFromInfix(String infix) -- 参数“infix”是包含中缀表达式的字符串。 树应该基于中缀表达式构建。 中缀表达式中的标记用空格分隔。 如果在调用函数之前树中包含节点,则需要先删除现有节点。 如果新树构建成功,则返回 true。 如果遇到错误,则返回 false。

void printInfixExpression() -- 打印出当前二叉表达式树的中缀表达式。 应该通过使用私有(递归)版本来做到这一点

void printPostfixExpression() -- 打印出当前二元表达式树的后缀表达式。 使用私有递归函数来帮助

int size() -- 使用私有递归函数返回树中的节点数

bool isEmpty() -- 如果树为空则返回真

int LeafNodes() -- 返回树中叶节点的数量。 (使用私有递归函数来帮助)

私有辅助函数(所有必需的私有成员函数必须递归实现):

void printInfixExpression(BinaryNode n) :打印相应的全括号中缀表达式。 你不应该有不必要的括号。

void makeEmpty(BinaryNode t) :删除树中根为t 的所有节点。

void printPostfixExpression(BinaryNode n) :打印相应的后缀表达式。

int size(BinaryNode t) :返回树中以t 为根的节点数。

int LeafNodes(BinaryNode t) :返回以t 为根的树中的叶节点数。

后缀表示法:后缀表示法是一种写出没有括号的算术表达式的明确方式。 它被定义为如果 (exp1) op (exp2) 是一个正常的全括号表达式,其操作是 op,则其后缀版本是 pexp1 pexp2 op,其中 pexp1 是 exp1 的后缀版本,而 pexp2 是 exp2 的后缀版本。 单个数字或变量的后缀版本就是该数字或变量。 因此,例如, ((5+2) * (8-3))/4的后缀版本是 5 2 + 8 3 - * 4 /

从后缀表达式构建 BET :从后缀表达式构建二叉表达式树的基本操作非常简单。 你只需要一个堆栈。 每次遇到操作数(数字、变量)时,从它创建一个树节点并将其压入堆栈顶部。 如果遇到运算符,只需弹出顶部的两个操作数节点,然后将一个以运算符为根、两个操作数为其左右子节点的新树节点推回到堆栈中。 从表达式中读取每个标记后,堆栈中应该有一个树节点,即二叉表达式树。 如果您有更多或更少,则表达式中存在错误。

从中缀表达式构建 BET :从中缀表达式(不一定带括号)构建二叉表达式树的基本操作类似于计算算术表达式的操作。 在这种情况下,您需要两个堆栈,一个用于运算符,一个用于操作数。 每次读取表达式中的操作数时,都会将其推入操作数堆栈的顶部。 每次读取运算符时,将其压入运算符堆栈,但首先为堆栈中已有的所有更高或相等优先级的运算符弹出并创建子树。 每次要为运算符创建子树时,都需要弹出运算符和两个操作数,并使操作数成为运算符的左右子项。 然后您将生成的子树推回到操作数堆栈上。 当您到达表达式的末尾时,对运算符堆栈上的所有剩余运算符执行相同的操作。 最后,您应该有一个空的运算符堆栈,并且操作数堆栈上只有一个树节点,它是您的二元表达式树的根。 将后缀转换为中缀表达式:。 使用二叉表达式树将后缀表达式转换为中缀表达式涉及两个步骤。 首先,从后缀表达式构建一个二叉表达式树。 其次,使用树的中序遍历打印二叉表达式树的节点。

将中缀转换为后缀表达式:使用二叉表达式树将中缀表达式转换为后缀表达式包括两个步骤。 首先,从中缀表达式构建一个二叉表达式树。 其次,使用树的后序遍历打印二叉表达式树的节点。 注意,打印中缀表达式时,需要添加括号,以确保中缀表达式与对应的后缀表达式和二叉表达式树具有相同的值(和相同的计算顺序)。 您的结果不应添加不必要的括号。 中缀表达式中的标记也应该用空格分隔。 下面是几个后缀表达式和相应的中缀表达式的例子。

postfix expression  infix expression
4 50 6 + +          ( 4 + ( 50 + 6 ) )
4 50 + 6 +          ( ( 4 + 50 ) + 6 )
4 50 + 6 2 * +        ( ( 4 + 50 ) + ( 6 * 2 ) )
4 50 6 + + 2 *        ( ( 4 + ( 50 + 6 ) ) * 2 )
a b + c d e + * *   ( ( a + b ) * ( c * ( d + e ) ) )

下面还包括一​​个驱动程序 Main.java。 这是一个示例测试程序,将在您的实现上运行一些测试。 但是,您的类将不仅仅使用这个示例驱动程序进行测试。 建议您自己编写其他驱动程序,以进行更彻底的测试。 这个测试程序的输出也包含在下面。

一般要求 • 适当地记录您的代码,使其可读且易于导航。 • 对于此项目,您可以使用 Java 中的 ArrayList 和 Stack 实现。 (java.util.Stack, java.util.ArrayList) • 你编写的任何辅助函数都应该在私有部分

  public static void main(String[] args) {
    try {
      System.out.println("\n\ntest1: a b c + * d -");
      BET test = new BET("a b c + * d -" , 'p');
      System.out.print("postfix: ");
      test.printPostfixExpression();
      System.out.print("infix: ");
      test.printInfixExpression();
      System.out.print("size: ");
      System.out.println(test.size());
      System.out.print("isEmpty: ");
      System.out.println(test.isEmpty());
      System.out.print("# of leaves: ");
      System.out.println(test.leafNodes());
      System.out.println("\n\ntest2: ( 3 + 2 ) * 3 + 1");
      test = new BET("( 3 + 2 ) * 3 + 1" , 'i');
      System.out.print("postfix: ");
      test.printPostfixExpression();
      System.out.print("infix: ");
      test.printInfixExpression();
      System.out.print("size: ");
      System.out.println(test.size());
      System.out.print("isEmpty: ");
      System.out.println(test.isEmpty());
      System.out.print("# of leaves: ");
      System.out.println(test.leafNodes());
      System.out.println("\n\ntest3: abc / 2 / f3 + z4 - 1 * 2");
      test.buildFromInfix("abc / 2 / f3 + z4 - 1 * 2");
      System.out.print("postfix: ");
      test.printPostfixExpression();
      System.out.print("infix: ");
      test.printInfixExpression();
      System.out.print("size: ");
      System.out.println(test.size());
      System.out.print("isEmpty: ");
      System.out.println(test.isEmpty());
      System.out.print("# of leaves: ");
      System.out.println(test.leafNodes());
      System.out.println("\n\ntest4: ( 3 + 2 * 3 + 1");
      test = new BET("( 3 + 2 * 3 + 1" , 'i');
      System.out.print("postfix: ");
      test.printPostfixExpression();
      System.out.print("infix: ");
      test.printInfixExpression();
      System.out.print("size: ");
      System.out.println(test.size());
      System.out.print("isEmpty: ");
      System.out.println(test.isEmpty());
      System.out.print("# of leaves: ");
      System.out.println(test.leafNodes());
    }
    catch(IllegalStateException e) {

      System.out.println(e.getMessage());
    }
  }
}

输出:

test1: a b c + * d -
postfix: a b c + * d -
infix: ( ( a * ( b + c ) ) - d )
size: 7
isEmpty: false
# of leaves: 4
test2: ( 3 + 2 ) * 3 + 1
postfix: 3 2 + 3 * 1 +
infix: ( ( ( 3 + 2 ) * 3 ) + 1 )
size: 7
isEmpty: false
# of leaves: 4
test3: abc / 2 / f3 + z4 - 1 * 2
postfix: abc 2 / f3 / z4 + 1 2 * -
infix: ( ( ( ( abc / 2 ) / f3 ) + z4 ) - ( 1 * 2 ) )
size: 11
isEmpty: false
# of leaves: 6
test4: ( 3 + 2 * 3 + 1
Invalid notation: ( 3 + 2 * 3 + 1

这是一个经典的问题,可以使用堆栈数据结构来解决。 看看这篇文章。

https://runestone.academy/runestone/books/published/pythonds/BasicDS/InfixPrefixandPostfixExpressions.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM