概念
- 什么是前缀表达式?
- 前缀表达式,其实就是一个中缀表达式 AOB => OAB (A、B是式子、O 为运算符),将运算符向前放
中缀转前缀举例
- 中缀表达式:(a + b)* c - (d / c)
- 第一步:根据运算规则(从左至右,优先级高优先),先去计算 a + b ,此时 A = a B = b O = +,中转前 AOB=>OAB=>+ab
- 第二步:根据运算规则,接下来去计算 (+ab) * c ,此时 A = +ab B = c O = *, 中转前 AOB=>OAB=>*+abc
- 第三步:根据运算规则,接下来去计算 d / c,此时 A = d B = c O = /,中转前 AOB=>OAB=> /dc
- 第四步:根据运算规则,接下来去计算 (*+abc) - (/dc) , 此时 A = *+abc B = /dc O = -,中转前AOB=>OAB=> -*+abc /dc
- 后缀表达式即是: -*+abc /dc
综上,我们可以看出,其实中缀转前缀,就是根据运算规则,找到我们表达式中最先计算的两项和运算符,然后,将其运算符放前边,并且要保持 A 和 B 的相对顺序不变,依次执行,直到转化成前缀表达式
中缀转前缀过程
详细规则:
- 初始化一个栈,存储 运算符
- 从右到左扫描(依次前放字符)
- 遇到操作数。直接加入前缀表达式
- 遇到界限符。遇到 “)” 直接入栈,遇到 “(” 则依次弹出栈内运算符并加入前缀表达式,直到弹出 “)” 为止 注意:“( )” 不加入前缀表达式
- 遇到运算符。依次弹出栈中优先级高于当前运算符的所有运算符,并加入前缀表达式,若碰到 “)” 或 栈空则停止。之后再把当前运算符入栈。
- 处理完所有字符后,将栈中剩余运算符依次弹出,并加入前缀表达式
注意:
①:中转前是依次 将字符 前放,中转后是依次将字符 后放
②:遇到运算符,中转前是 将栈中优先级高的弹出 。中转后是 将栈中优先级高于和等于的弹出
详细执行过程:
Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 100
// 运算符优先级函数
int precedence(char op) {
if (op == '+' || op == '-') {
return 1;
} else if (op == '*' || op == '/') {
return 2;
} else {
return 0;
}
}
// 中缀转前缀实现
void infix_to_prefix(char* infix, char* prefix) {
char stack[MAX_SIZE]; // 定义一个栈,用来存放 运算符
int top = -1; // 定义 栈顶指针
int i, j , temp , k=0;
// 遍历到最后一个字符,k 最后指向 '\0' 的位置
while(infix[k] != '\0'){
++k;
}
// 从右至左遍历中缀字符数组
for (i = k-1, j = 0; i >= 0; --i) {
// 判断,如果是字符,将其存入前缀字符数组中
if (infix[i] >= 'a' && infix[i] <= 'z') {
prefix[j++] = infix[i];
} else if (infix[i] == ')') { // 如果是 右括号,直接放入栈中
stack[++top] = infix[i];
} else if (infix[i] == '(') { // 如果是 左括号
// 将栈中 右括号之前的 运算符依次弹出,并进入前缀数组中
while (top != -1 && stack[top] != ')') {
prefix[j++] = stack[top--];
}
// 再减一次是为了:弹出 右括号
top--;
} else {
// 栈不空,并且当栈顶运算符优先级 大于 扫描到中缀运算符优先级,将栈中元素依次弹出,放入前缀数组中
while (top != -1 && precedence(stack[top]) > precedence(infix[i])) {
prefix[j++] = stack[top--];
}
// 再将扫描到的中缀运算符,放入栈中
stack[++top] = infix[i];
}
}
// 当扫描完后,将栈中元素依次弹出,并放入前缀表达式数组中
while (top != -1) {
prefix[j++] = stack[top--];
}
// 进行逆置
for(i = 0, k = j-1; i < k; ++i,--k){
temp = prefix[i];
prefix[i] = prefix[k];
prefix[k] = temp;
}
// 设置字符数组结束符
prefix[j] = '\0';
}
int main() {
char infix[MAX_SIZE];
char prefix[MAX_SIZE];
printf("输入中缀表达式: ");
scanf("%s", infix);
infix_to_prefix(infix, prefix);
printf("前缀表达式是: %s\n", prefix);
return 0;
}