您的位置:首页 > 理论基础 > 数据结构算法

【数据结构】前缀后缀表达式求值

2018-03-13 21:18 567 查看
前缀表达式和后缀表达式是什么呢?

对于任何算数表达式来说,如果每个操作符跟在它的两个操作数之后,而不是两个操作数之间,那么这个表达式就是后缀表达,又称为逆波兰表达式,如:

3 5 + 7 * 1 -

如果是跟在两个操作数之间,那么这个表达式就是中缀表达式,如:

(3 + 5) * 7 - 1

如果是在两个操作数之前,那么这个表达式就是前缀表达式,又称波兰表达式,如:

-*+3 5 7 1

前缀表达式求值,思路如下:

因为前缀表达式,操作符肯定都在前面,因此把操作符一一入栈:



然后,如果遇到数字了,就把取出一个操作符,再得到两个操作数,进行处理然后继续循环,直到所有的操作数都处理完毕

代码如下:

int PreFix(SeqStack* seq,char* str) {
if (seq == NULL || str == NULL) {
return;
}
int num1 = 0;
int num2 = 0;
int flag = 0;
//循环处理直到遍历完表达式
while (*str != '\0') {
if (*str == '-' || *str == '+' || *str == '*') {
SeqStackPush(seq, *str);
}
else {
if (flag == 0) {
//由于不知道咋处理,所以我设了一个标志,只有第一次是从表达式中获取两个操作数的
num1 = *str - '0';
num2 = *++str - '0';
flag = 1;
}
else {
num2 = *str - '0';
}
//从栈中取出操作符
char s = SeqStackTopValue(seq);
SeqStackPop(seq);
if (s == '+') {
num1 = num1 + num2;
}
if (s == '-') {
num1 = num1 - num2;
}
if (s == '*') {
num1 = num1 * num2;
}
}
str++;
}
return num1;
}

#if 1
int main() {
char* str = "-*+3571";
SeqStack seq;
SeqStackInit(&seq);
int num = PreFix(&seq, str);
printf("expcet 55, actual :%d\n", num);
system("pause");
return 0;
}
#endif


注意,我这里的数字都是个位数字,我就不改这段代码了,如果遇到两位以上的数字可以用以下这段代码:

while(*str >= '0' && *str <= '9') {
num = num*10 + (num - '0');
}


前缀表达式的递归求法:

char* str = "-*+3571"; int i;
int PreFix2() {
int num = 0;
if (*str == '+') {
str++;
return PreFix2() + PreFix2();
}
if (*str == '-') {
str++;
return PreFix2() - PreFix2();
}
if (*str == '*') {
str++;
return PreFix2() * PreFix2();
}
if (*str >= '0' && *str <= '9') {
num = *str++ - '0';
}
return num;
}


中缀表达式的求表达式我没写,但是有中缀表达式转换后缀表达式:

例如这个中缀表达式:(3 + 5) * 7 - 1 ,要想转换成后缀表达式,就是遇到操作符就先保存起来,如果接下来遇到‘)’符号,再把保存起来的操作符加上去,然后就继续循环直到表达式结束

int main(int argc, char* argv[]) {
char* a = argv[1];
int i, N = strlen(a);
SeqStack seq;
SeqStackInit(&seq);
for (i = 0; i < N; ++i) {
if (a[i] == ')') {
printf("%c", SeqStackTopValue(&seq));
SeqStackPop(&seq);
}
if (a[i] == '+' || a[i] == '*') {
SeqStackPush(&seq, a[i]);
}
if (a[i] >= '0' && a[i] <= '9') {
printf("%c", a[i]);
}
}
}


后缀表达式求值也是用到栈,如果遇到操作数就把操作数压栈,如果遇到操作符就出栈两个操作数然后运算再把运算后的值压入到栈里,再继续遍历表达式,直到表达式完成,栈顶元素(也是栈里唯一的元素)就是求出的值

代码如下:

int Suf_Result(SeqStack* seq1, char* exp, int size) {
if (seq1 == NULL) {
printf("栈指针传入错误!\n");
return 0;
}
if (exp == NULL) {
printf("表达式为空!\n");
return 0;
}
if (size == 0) {
return 0;
}
// 1.把这个表达式逆序压栈
char* str = exp + size - 1;
while (str != exp) {
SeqStackPush(seq1, *str);
str--;
}
SeqStackPush(seq1, *str);
int arr[12];
int sz = 0;
while (!SeqStackEmpty(seq1)) {
char ch = SeqStackTopValue(seq1);
SeqStackPop(seq1);
if (ch >= '0' && ch <= '9') {
arr[sz++] = ch - '0';
}
else if(ch == '+' || ch == '-' || ch == '*') {
int num1 = arr[sz - 1];
sz--;
int num2 = arr[sz - 1];
sz--;
if (ch == '+') {
arr[sz++] = num1 + num2;
}
else if (ch == '-') {
arr[sz++] = num2 - num1;
}
else {
arr[sz++] = num1 * num2;
}
}
}
return arr[sz - 1];
}


这里跟前缀是一样的,如果数字是两位或者三位就用上面那个循环,如果是遇到空格了也用一个循环跳过空字符,比如:

while(*str == ' ') str++;


这里只是简单的写了一下前缀后缀的求值,包括中缀转后缀,好多地方可能会有一些bug,但是大体上思路就是这样
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息