中缀表达式计算过程
假设我们有一个中缀表达式:3 + 4 * 2
。在中缀表达式中,运算符位于操作数的中间。
-
扫描表达式: 从左到右扫描表达式,按照运算符的优先级进行计算。
-
根据优先级计算: 遇到乘法运算符
*
,我们首先计算相应的操作数,即4 * 2
,得到结果8
。 -
替换子表达式: 将子表达式
4 * 2
替换为其结果8
,得到新的表达式3 + 8
。 -
继续计算: 最后,我们计算加法运算符
+
,得到最终结果11
。
波兰式计算过程
现在让我们来看看同样的表达式的逆波兰式表示:3 4 2 * +
。
-
扫描表达式: 从左到右扫描逆波兰式表达式。
-
使用栈进行计算: 遇到数字时,将其压入栈中。遇到运算符时,从栈中弹出相应数量的操作数进行计算,并将结果重新压入栈中。
- 我们首先将
3
压入栈中。 - 然后遇到
4
,将其压入栈中。 - 接着遇到
2
,同样将其压入栈中。 - 遇到乘法运算符
*
,弹出栈顶的两个操作数4
和2
,计算得到结果8
,将其压入栈中。 - 最后,遇到加法运算符
+
,弹出栈顶的两个操作数3
和8
,计算得到最终结果11
。
- 我们首先将
-
返回结果: 最终结果为栈顶的元素,即
11
。
通过以上过程,我们成功地计算了给定的表达式,得到了相同的结果。
现在有两个问题
- 问题一、中缀表达式转后缀表达式
- 问题二、后缀表达式的计算
问题一
中缀表达式转换为后缀表达式通常使用栈来实现,以下是转换的基本步骤:
- 初始化一个空栈和一个空字符串,用于存储最终的后缀表达式。
- 从左到右扫描中缀表达式的每个字符。
- 如果遇到操作数(数字),直接将其添加到后缀表达式字符串中。
- 如果遇到运算符,分两种情况:
- 如果栈为空,或者栈顶元素是左括号,则将当前运算符压入栈中。
- 否则,如果当前运算符的优先级小于或等于栈顶运算符的优先级,则将栈顶运算符弹出并添加到后缀表达式字符串中,直到栈为空或者遇到了左括号,然后将当前运算符压入栈中。
- 如果遇到左括号,直接将其压入栈中。
- 如果遇到右括号,不断地将栈顶运算符弹出并添加到后缀表达式字符串中,直到遇到了左括号为止,然后将左括号从栈中弹出但不添加到后缀表达式中。
- 扫描完整个中缀表达式后,将栈中剩余的运算符依次弹出并添加到后缀表达式字符串中。
下面是一个用 JavaScript 实现中缀表达式转换为后缀表达式的示例代码:
javascript
function infixToPostfix(infixExpression) {
const precedence = {
'+': 1,
'-': 1,
'*': 2,
'/': 2
};
let postfixExpression = '';
const stack = [];
for (let i = 0; i < infixExpression.length; i++) {
const token = infixExpression[i];
if (/\d/.test(token)) {
// 如果是数字,直接添加到后缀表达式中
postfixExpression += token;
} else if (token === '(') {
// 如果是左括号,直接压入栈中
stack.push(token);
} else if (token === ')') {
// 如果是右括号,将栈顶元素依次弹出并添加到后缀表达式中,直到遇到左括号
while (stack.length > 0 && stack[stack.length - 1] !== '(') {
postfixExpression += stack.pop();
}
stack.pop(); // 弹出左括号
} else {
// 如果是运算符
while (stack.length > 0 && precedence[token] <= precedence[stack[stack.length - 1]]) {
// 当前运算符优先级小于等于栈顶运算符优先级时,将栈顶运算符弹出并添加到后缀表达式中
postfixExpression += stack.pop();
}
stack.push(token); // 将当前运算符压入栈中
}
}
// 将栈中剩余的运算符依次弹出并添加到后缀表达式中
while (stack.length > 0) {
postfixExpression += stack.pop();
}
return postfixExpression;
}
const infixExpression = "3 + 4 * 2";
const postfixExpression = infixToPostfix(infixExpression);
console.log("中缀表达式转后缀表达式:", postfixExpression); // 输出 "342*+"
通过以上代码,我们可以将中缀表达式转换为后缀表达式。在这个例子中,中缀表达式 3 + 4 * 2
被转换为后缀表达式 342*+
。
问题二
这个就简单了
当使用后缀表达式计算算术表达式时,通常采用栈数据结构来辅助计算。 以下是上述算法的更详细描述:
-
初始化一个空栈: 创建一个空的栈,用于存储操作数和中间计算结果。
-
从左到右扫描后缀表达式: 从后缀表达式的第一个字符开始,逐个读取字符直到最后一个字符。
-
处理操作数: 如果当前字符是操作数(即数字),则将其转换为整数,并将其压入栈中。
-
处理运算符: 如果当前字符是运算符,那么从栈中弹出两个操作数,将它们与当前运算符进行相应的运算,然后将运算结果压入栈中。
- 对于加法运算符
+
,弹出栈顶的两个操作数进行相加,并将结果压入栈中。 - 对于减法运算符
-
,弹出栈顶的两个操作数进行相减(第二个操作数减去第一个操作数),并将结果压入栈中。 - 对于乘法运算符
*
,弹出栈顶的两个操作数进行相乘,并将结果压入栈中。 - 对于除法运算符
/
,弹出栈顶的两个操作数进行相除(第二个操作数除以第一个操作数),并将结果压入栈中。
- 对于加法运算符
-
重复步骤 3 和 4: 重复执行步骤 3 和 4,直到扫描完整个后缀表达式。
-
获取计算结果: 当扫描完整个后缀表达式后,栈中应该只剩下一个元素,即为表达式的计算结果。
这个算法通过一次遍历后缀表达式并使用栈来存储操作数和中间结果,实现了后缀表达式的计算。
js
function evaluatePostfixExpression(postfixExpression) {
const stack = [];
for (let i = 0; i < postfixExpression.length; i++) {
const token = postfixExpression[i];
if (/\d/.test(token)) {
// 如果是数字,将其转换为整数并压入栈中
stack.push(parseInt(token));
} else {
// 如果是运算符,从栈中弹出两个操作数进行运算
const operand2 = stack.pop();
const operand1 = stack.pop();
let result;
switch (token) {
case '+':
result = operand1 + operand2;
break;
case '-':
result = operand1 - operand2;
break;
case '*':
result = operand1 * operand2;
break;
case '/':
result = operand1 / operand2;
break;
}
// 将运算结果压入栈中
stack.push(result);
}
}
// 栈中最终剩余的元素即为表达式的计算结果
return stack.pop();
}
const postfixExpression = "342*+";
const result = evaluatePostfixExpression(postfixExpression);
console.log("后缀表达式计算结果:", result); // 输出 11