基于链表实现栈:如何读取后缀表达式文件并填充栈?
没问题,我来帮你搞定用链表栈处理后缀表达式文件的事儿!下面一步步给你讲清楚怎么实现:
用链表栈处理后缀表达式文件的完整实现指南
一、先确认你的GenericStack类具备必要方法
你已经定义了GenericStack和Node类,但要确保它有栈的核心操作:push、pop、isEmpty。如果还没完全实现,这里补全一下:
public class GenericStack<T> { private Node<T> top; public GenericStack() { top = null; } // 压栈:把元素放到栈顶 public void push(T data) { Node<T> newNode = new Node<>(data); newNode.next = top; top = newNode; } // 弹栈:取出栈顶元素并移除,栈空时抛出异常 public T pop() { if (isEmpty()) { throw new IllegalStateException("栈为空,无法弹出元素"); } T data = top.data; top = top.next; return data; } // 判断栈是否为空 public boolean isEmpty() { return top == null; } // 内部Node类,用于构建链表 private static class Node<T> { T data; Node<T> next; Node(T data) { this.data = data; this.next = null; } } }
二、在Evaluator类中实现文件读取与栈处理逻辑
接下来,在你的Evaluator类的main方法里,我们要完成读取文件→分割表达式→处理栈计算的完整流程:
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; public class Evaluator { public static void main(String[] args) { // 这里替换成你的输入文件路径,也可以通过命令行参数传入args[0]更灵活 String filePath = "postfix_expressions.txt"; // 因为后缀表达式计算常用整数,这里泛型指定为Integer,需要浮点数就改成Double GenericStack<Integer> stack = new GenericStack<>(); try { // 读取文件所有行,每行对应一个后缀表达式 List<String> lines = Files.readAllLines(Paths.get(filePath)); for (String line : lines) { // 把每行按空格分割成单个token(数字或运算符),支持多空格分隔 String[] tokens = line.trim().split("\\s+"); for (String token : tokens) { if (isNumeric(token)) { // 是数字就转成Integer压入栈 stack.push(Integer.parseInt(token)); } else { // 是运算符就弹出两个操作数计算,注意操作数顺序 if (stack.isEmpty()) { throw new IllegalArgumentException("无效表达式:运算符缺少操作数"); } int operand2 = stack.pop(); // 后弹出的是第二个操作数 if (stack.isEmpty()) { throw new IllegalArgumentException("无效表达式:运算符缺少操作数"); } int operand1 = stack.pop(); // 先弹出的是第一个操作数 // 计算结果并压回栈 int result = calculate(operand1, operand2, token); stack.push(result); } } // 处理完一行后,栈顶就是该表达式的结果 if (!stack.isEmpty()) { System.out.println("表达式 '" + line + "' 的结果:" + stack.pop()); } } } catch (IOException e) { System.err.println("读取文件出错:" + e.getMessage()); } catch (IllegalArgumentException | ArithmeticException | IllegalStateException e) { System.err.println("处理出错:" + e.getMessage()); } } // 辅助方法:判断字符串是否是整数 private static boolean isNumeric(String str) { try { Integer.parseInt(str); return true; } catch (NumberFormatException e) { return false; } } // 辅助方法:根据运算符计算结果 private static int calculate(int operand1, int operand2, String operator) { return switch (operator) { case "+" -> operand1 + operand2; case "-" -> operand1 - operand2; case "*" -> operand1 * operand2; case "/" -> { if (operand2 == 0) { throw new ArithmeticException("除数不能为0"); } yield operand1 / operand2; } default -> throw new IllegalArgumentException("不支持的运算符:" + operator); }; } }
三、关键步骤说明
- 文件读取:用
Files.readAllLines可以快速读取小文件,如果你处理的是大文件,建议用BufferedReader逐行读取,避免内存占用过高。 - Token分割:用
\\s+作为分隔符,可以匹配多个空格,避免表达式中多个空格导致的空token问题。 - 栈操作逻辑:后缀表达式的核心就是「遇数压栈,遇运算符弹栈计算」,这里要注意操作数的顺序:比如
6 5 2 3 + 8 * + 3 + *这个表达式,遇到+时,要弹出3和2,计算2+3=5,再把5压栈,以此类推。 - 异常处理:覆盖了文件读取失败、表达式格式错误、除数为0、栈空操作等常见异常,让程序更健壮。
四、测试一下
假设你的输入文件postfix_expressions.txt里有一行:
6 5 2 3 + 8 * + 3 + *
运行程序后,会输出:
表达式 '6 5 2 3 + 8 * + 3 + *' 的结果:288
这个结果是正确的,手动计算验证:((2+3)*8 +5 +3)*6 = (5*8+8)*6 = (40+8)*6=48*6=288。
内容的提问来源于stack exchange,提问作者Jane Brown
相关产品推荐
相关产品推荐

