前缀 中缀 后缀表达式

本文详细介绍了前缀、中缀和后缀表达式及其运算过程,特别是前缀表达式(- × + 3 4 5 6)和后缀表达式(3 4 + 5 × 6 -)的计算方法。通过比较,强调了后缀表达式在计算上的优势,并提供了中缀表达式转后缀表达式的转换策略。
摘要由CSDN通过智能技术生成

前缀表达式(Polish expression, 波兰表达式)

前缀表达式

前缀表达式的运算符位于操作数之前。 (3+4)×5-6 对应的前缀表达式就是 - × + 3 4 5 6。

运算过程

例如:(3+4)×5-6 对应的前缀表达式就是 - × + 3 4 5 6 , 针对前缀表达式求值步骤如下:

  • 从右至左扫描,将6、5、4、3压入堆栈
  • 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素),计算出3+4的值,得7,再将7入栈
  • 接下来是×运算符,因此弹出7和5,计算出7×5=35,将35入栈
  • 最后是-运算符,计算出35-6的值,即29,由此得出最终结果

中缀表达式

中缀表达式就是常见的运算表达式,如(3+4)×5-6。此表达式需判断运算符的优先级。中缀表达式的求值是我们人最熟悉的,但是对计算机来说却不好操作(前面我们讲的案例就能看的这个问题,因为中缀表达式存在运算符优先级的问题),因此,在计算结果时,往往会将中缀表达式转成其它表达式来操作(一般转成后缀表达式)。

中缀表达式(Infix expression): 实现简单计算器

思路分析

  • 定义两个栈: 一个是数值栈, 另一个运算符栈
  • 定义两个方法: 判断运算符优先级的方法和计算已入栈数值的方法
  • 逐个循环扫描输入的中缀表达式, 如果是数字就入数值栈, 如果是运算符, 则需要与运算符栈的栈顶运算符比较优先级. 如果优先级高于栈顶的运算符, 则直接入栈(运算符栈), 否则, 从数值栈取2元素(数值), 在从运算符栈取栈顶元素做运算, 将运算结果再存入数值栈, 之后将当前运算符入栈(运算符栈)
/** 定义数组栈*/
class ArrayStack {
   
    /** 栈大小*/
    private int maxSize;
    /** 通过该数组存放数据, 模拟栈数据结构*/
    private int[] stack;
    /** 栈顶的 index, 初始值为-1*/
    private int top = -1;

    public ArrayStack(int maxSize) {
   
        this.maxSize = maxSize;
        stack = new int[maxSize];
    }

    /** 栈满*/
    public boolean isFull() {
   
        return top == maxSize - 1;
    }

    /** 栈空*/
    public boolean isEmpty() {
   
        return top == -1;
    }

    /** 入/压栈*/
    public void push(int value) {
   
        if (isFull()) {
   
            System.out.println("入栈失败, 栈已满!");
            return;
        }
        top++;
        stack[top] = value;
    }

    /** 出/弹栈*/
    public int pop() {
   
        if (isEmpty()) {
   
            throw new RuntimeException("出栈失败, 没有数据!");
        }
        int value = stack[top];
        top--;
        return value;
    }

    /** 从栈顶开始打印所有内容*/
    public void list() {
   
        if (isEmpty()) {
   
            System.out.println("打印失败, 没有数据!");
            return;
        }
        for (int i = top; i >= 0; i--) {
   
            System.out.printf("stack[%d]=%d\n", i, stack[i]);
        }
    }

    /** 查看栈顶元素内容*/
    public int peek() {
   
        return stack[top];
    }

    /** 运算符的优先级*/
    public int operPriority(int oper) {
   
        if (oper == '*'|| oper == '/') {
   
            return 1;
        } else if(oper == '+'|| oper == '-') {
   
            return 0;
        } else {
   
            /** 无效的表达式*/
            return -1;
        }
    }

    /** 判断是不是一个运算符*/
    public boolean isOper(char val) {
   
        return val == '+' || val=='-' || val=='*' || val=='/';
    }

    /** 计算方法*/
    public int cal(int num1, int num2, int oper) {
   
        int res = 0;
        switch (oper) {
   
            case '+':
                res = num1 + num2;
                break;
            case '-':
                res = num2 - num1;
                break;
            case '*':
                res = num1 * num2;
                break;
            case '/':
                res = num2 / num1;
                break;
            default:
                break;
        }
        return res;
    }
}

public class CalculatorApp {
   
    public static void main(String[] args) {
   
        System.out.println("请输入要计算的中缀表达式: ");
        Scanner in = new Scanner(System.in);
        String expression = in.nextLine();
        in.close();

        /** 定义数值栈*/
        ArrayStack numStack = new ArrayStack(10);
        /** 定义运算符栈*/
        ArrayStack operStack = new ArrayStack(10);

        /** 表达式每个字符位索引*/
        int index = 0;
        /** 每次循环获取到的字符*/
        char ch;
        /** 计算多位数时, 用于拼接的字符串变量*/
        String keepnum = "";
        /** 当计算时, 从数值栈出栈的第一个数值*/
        int num1 = 0;
        /** 当计算时, 从数值栈出栈的第而二个数值*/
        int num2 = 0;
        /** 运算符 char <-> int*/
        int oper = 0;
        /** 计算结果*/
        int res = 0;
        while (true) {
   
            /** 每次循环获取单个字符*/
            ch = expression.substring(index, index + 1).charAt(0);
            /** 判断是否为运算符*/
            if (operStack.isOper(ch)) {
   
                if (operStack.isEmpty()) {
   
                    /** 如果定义运算符栈为空, 直接入栈*/
                    operStack.push(ch);
                } else {
   
                    /** 判断当前运算符(如 +)的优先级是否低于栈顶运算符(如 x), 如果低或相等通过*/
                    if (operStack.operPriority(ch) <= operStack.operPriority(operStack.peek())) {
   
                        /** 之前已入栈的数值与运算符取出, 开始计算*/
                        num1 = numStack.pop();
                        num2 = numStack.pop();
                        oper = operStack.pop();
                        res = operStack.cal(num1, num2, oper);
                        /** 数值栈的累计值计算后, 将值重新入栈*/
                        numStack.push(res);
                        /** 当前运算符(如 +), 入栈*/
                        operStack
为了回答你的问题,我将介绍前缀中缀后缀表达式,并展示如何在它们之间进行转换。 1. 前缀表达式(也称为波兰式): 在前缀表达式中,运算符位于操作数之前。例如,表达式 "2 + 3" 的前缀形式为 "+ 2 3"。 2. 中缀表达式: 中缀表达式是我们通常使用的常规数学表达式形式。它使用括号和运算符的优先级来表示运算顺序。例如,表达式 "2 + 3" 就是一个中缀表达式。 3. 后缀表达式(也称为逆波兰式): 在后缀表达式中,运算符位于相应的操作数之后。例如,表达式 "2 + 3" 的后缀形式为 "2 3 +"。 现在,我将向你展示如何将中缀表达式转换为前缀后缀表达式。 从中缀前缀转换: 1. 反转中缀表达式。 2. 将反转的中缀表达式转换为后缀形式。 3. 反转后缀表达式即可得到前缀表达式。 从中缀到后缀转换: 1. 创建一个空栈和一个空输出列表。 2. 从左到右扫描中缀表达式的每个符号。 - 如果遇到操作数,将其添加到输出列表。 - 如果遇到运算符,将其压入栈中。 - 如果遇到左括号,将其压入栈中。 - 如果遇到右括号,则连续弹出栈顶元素并将其添加到输出列表,直到遇到左括号为止。注意:左括号不会被添加到输出列表中。 如果栈顶元素是左括号,则将其弹出栈。 - 如果遇到的运算符具有比栈顶运算符更高的优先级,将其压入栈中。 如果遇到的运算符具有与栈顶运算符相同的优先级,并且是左结合的运算符,则将栈顶运算符弹出并添加到输出列表中,然后将当前运算符压入栈中。 如果遇到的运算符具有与栈顶运算符相同的优先级,并且是右结合的运算符,则将当前运算符压入栈中。 - 重复步骤2直到扫描完整个中缀表达式。 3. 将栈中剩余的所有运算符弹出并添加到输出列表中。 4. 输出列表即为转换后的后缀表达式。 希望这个解释对你有帮助!如果你有其他问题,可以继续问我。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值