栈解决简单的后缀表达式运算

230 阅读2分钟

栈实现后缀表达式转化和计算

利用栈的先进后出特性可以方便地将中缀表达式转换为后缀表达式:

转换函数定义 void trans(char* exp, char postexp[]) exp为输入的算术表达式字符串,postexp为结果字符数组。此算法还需要一个运算符栈用来转换所有的运算符。

对于输入的字符串依次读取,如果读入的是数字,则直接读入postexp数组,并在读取完一个数字后加上‘#’表示一个数字读取完,方便后续计算后缀表达式。

若读入的是一个运算符,则利用运算符转换栈来转换,有如下情况:

  • 读入一个运算发,此时栈为空,直接push。
  • 栈内有预算符,则和栈顶运算符比较优先级,若优先级高于栈顶元素(读入运算符要先运算)则直接push,否则将栈顶元素出栈,输入到postexp数组,重复和栈顶比较。
  • 若栈顶是'('则直接push

将整个exp字符串读完以后,将运算符栈依次出栈到postexp数组,完成转换。

可以到我的代码仓库查看源代码。


#pragma once
#include "SqStack.h"

void trans(char* exp, char postexp[])
{
	char e;
	SqStack* Optr;
	InitStack(Optr);
	int i = 0;
	while (*exp != '\0')
	{
		switch (*exp)
		{
		case'(':
			Push(Optr, '(');
			exp++;
			break;
		case')':
			Pop(Optr, e);
			while (e != '(')
			{
				postexp[i++] = e;
				Pop(Optr, e);
			}
			exp++;
			break;
		case'+':
		case'-':
			while (!StackEmpty(Optr))
			{
				GetTop(Optr, e);
				if (e != '(')
				{
					postexp[i++] = e;
					Pop(Optr, e);
				}
				else
					break;
			}
			Push(Optr, *exp);
			exp++;
			break;
		case'*':
		case'/':
			while (!StackEmpty(Optr))
			{
				GetTop(Optr, e);
				if (e == '*' || e == '/')
				{
					postexp[i++] = e;
					Pop(Optr, e);
				}
				else
					break;
			}
			Push(Optr, *exp);
			exp++;
			break;
		default:
			while (*exp >= '0' && *exp <= '9')
			{
				postexp[i++] = *exp;
				exp++;
			}
			postexp[i++] = '#';
		}
	}
	while (!StackEmpty(Optr))
	{
		Pop(Optr, e);
		postexp[i++] = e;
	}
	postexp[i] = '\0';
	DestroyStack(Optr);
}

后缀表达式的计算:

运算过程中需要一个运算数栈。

运算过程如下:

  • 对postexp数字依次读取,若是数字,则通过下述代码转换位数字并push。
			d = 0;
			while (*postexp >= '0' && *postexp <= '9')
			{
				d = 10 * d + *postexp - '0';
				postexp++;
			}
			Push1(Opnd, d);
			break;
  • 若是运算符,则从栈中取出两个数字进行相应的运算。

注意由于采用栈存储操作数,先读出的a,和后读出的b要注意运算次序,例如读入'/',则是b/a!

计算完即得出了最终结果

#pragma once
#include "SqStack1.h"
double compvalue(char* postexp)
{
	double a, b, c, d, e;
	SqStack1* Opnd;
	InitStack1(Opnd);
	while (*postexp != '\0')
	{
		switch (*postexp)
		{
		case'+':
		case'-':
			Pop1(Opnd, a);
			Pop1(Opnd, b);
			c = (*postexp == '+') ? (b + a) : (b - a);
			Push1(Opnd, c);
			break;
		case'*':
			Pop1(Opnd, a);
			Pop1(Opnd, b);
			c = b * a;
			Push1(Opnd, c);
			break;
		case'/':
			Pop1(Opnd, a);
			Pop1(Opnd, b);
			if (a != 0)
			{
				c = b / a;
				Push1(Opnd, c);
				break;
			}
			else {
				std::cout << "除数不能为零" << std::endl;
				exit(0);
			}
			break;
		default:
			d = 0;
			while (*postexp >= '0' && *postexp <= '9')
			{
				d = 10 * d + *postexp - '0';
				postexp++;
			}
			Push1(Opnd, d);
			break;
		}
		postexp++;
	}
	GetTop1(Opnd, e);
	DestroyStack1(Opnd);
	return e;
}