数据结构C语言版:利用栈将中缀表达式转为后缀表达式,进行四则运算求值

《数据结构》给出这样一道题目:

借助辅助栈,编写算法,计算一个后缀表示式T的值。

题目减少了将中缀表达式转换为后缀表达式的算法步骤。事实上,要实现四则运算求值,需要把中缀表达式转化为后缀表达式,再把后缀表达式进行运算得出结果。

 

一、中缀表达式与后缀表达式

1. 观察式子:1+2

平时我们所用的四则运算表达式都是运算符在两个数字中间的,所以称这种表达式为中缀表达式它需要判断括号匹配,需要判断加减乘除的优先级。

2. 观察式子:1 2 +

运算符在两个数字之后的表达式为后缀表达式

如果将式子「1」:6 + ( 4 - 2 ) × 3 + 9 ÷ 3

转化为式子「2」:6  4  2  -  3  × + 9  3  ÷ +

12  + 3 ==15

12   3   +==15

和式子「1」比,式子「1」中两个数字中间运算符在式子2中都在两个数字之后出现,称式子「2」为后缀表达式后缀表达式不需要考虑括号匹配、运算符优先级,简化运算。

 

二、中缀表达式转后缀表达式

1. 利用栈的特性,给出转换方法

从头到尾读取中缀表达式的每个对象,对不同对象按不同的情况处理。
①    运算数:直接输出;
②    左括号:压入堆栈;
③    右括号:将栈顶的运算符弹出并输出,直到遇到左括号(出栈,不输出)
④    运算符
•当优先级大于栈顶运算符时,则把它压栈;
•当优先级小于或等于栈顶运算符时,将栈顶运算符弹出并输出;再比较新的栈顶运算符,直到该运算符大于栈顶运算符优先级为止,然后将该运算符压栈;
⑤    若各对象处理完毕,则把堆栈中存留的运算符一并输出。

 

2. 以中缀表达式:6 + ( 4 - 2 ) × 3 + 9 ÷ 3 转后缀表达式为例

 

三、后缀表达式的运算

1. 规则:(用栈来进出运算的数字)

① 从左到右遍历中缀表达式的每一个数字和符号

② 若是数字,则进栈

③ 若是符号,则把处于栈顶的两个数字出栈,进行运算

④ 运算结果进栈

⑤ 直到获得最终结果

 

2. 以计算后缀表达式:6 4 2 - 3 × + 9 3 ÷ + 为例

 

四、算法的实现

算法需要两个栈,stack1 存放运算数 (num),stack2 存放运算符 (operator) 。分配空间、初始化这两个栈。

接口除了栈的基本操作外,还需要这些操作:判断、比较运算符的优先级、两数四则运算。用户输入的数据为中缀表达式,以%s的格式输入到 str ,循环遍历 str 的每一个字符,完成数字入栈、比较运算符的优先级等,还要注意第一个数是负数的特殊情况,注意用户错误输入的情况 。详细代码在本文暂略,可以参考:

https://github.com/wmsofts/Calculator_V1

https://github.com/wmsofts/Calculator_V2

https://github.com/wmsofts/Calculator_V3

(代码存在不完善的地方)

 

五、

对于题目:编写算法,计算一个后缀表示式T的值。简略代码如下:

1. 定义栈:

/*顺序栈的类型定义 */ 
typedef struct{
	ElemType *elem;  
	int *top;
	int size;
	int increment; //扩容时,增加的存储容量 
}SqStack;
SqStack S;
Status Input(char m[MAXSIZE]){
	int h = 0;
	for(; m[h - 1] != '#'; h++){ //输入以#结束 
		m[h] = getchar();
	}
	m[h] = '\0';
    return OK;
}

Status Calc(char m[MAXSIZE])
{
	int h = 0;
	int g = 0;
	for(; m[h] != '#'; h++){
		int k;
		char j;
		if(m[h] >= '0' && m[h] <= '9'){
			g = g * 10 + m[h] - '0';
		}
		else
			if((m[h] == ' ' || m[h] == '+' || m[h] == '-' || m[h] == '/' || m[h] == '*') && m[h-1] >= '0' && m[h-1] <= '9'){
				k = g;
				g = 0;
				Push(S, k);
			}
		if(m[h] == '+' || m[h] == '-' || m[h] == '/' || m[h] == '*')
		goto area;
		else{
			area:    j = m[h];
     		switch(j){
				case '+':{
				int c;
				c = Pop(S);
				int d;
				d = Pop(S);
				Push(S, d + c);
				break;
			}
				case '-':{
				int c;
				c = Pop(S);
				int d;
				d = Pop(S);
				Push(S, d - c);
				break;
			}
				case '*':{
				int c;
				c = Pop(S);
				int d;
				d = Pop(S);
				Push(S, d * c);
				break;
			}
				case '/':{
				int c;
				c = Pop(S);
				int d;
				d = Pop(S);
				Push(S, d / c);
				break;
			}
     		default:
      	break;
     }
   }
 }
    return OK;
}

调用:

int main(){
     InitStack(S);
     char m[MAXSIZE];
     Input(m);
     Calc(m);
     int result = Pop(S); 
     cout << result << endl;
}

————————————————————————

2. 如果这样定义栈,

typedef struct STRACK    
{
    double a[100];
    int top;
} STRACK;

代码可以改为: 

int main()
{
    double totle=0,e=0;
    char s[100];
    int i;

    STRACK L;
    L.top=-1;
    gets(s);
    for(i=0; s[i]!='@'; i++)
    {
        if(s[i]<='9'&&s[i]>='0')
        {
            L.top++;
            int temp=s[i]-'0';
            int k=i+1;
            while(s[k]!='@')                                          //利用while循环得到由多位由字符组成的数值
            {
                if(s[k]<='9'&&s[k]>='0')
                {
                    temp=10*temp+(s[k]-'0');
                    i++;
                    k++;
                }
                else break;
            }
            L.a[L.top]=temp;
        }
        else  if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/')        //遇到运算符进行计算
        {
            switch(s[i])
            {
            case '+':
                e=L.a[L.top-1]+L.a[L.top];
                break;
            case '-':
                e=L.a[L.top-1]-L.a[L.top];
                break;
            case '*':
                e=L.a[L.top-1]*L.a[L.top];
                break;
            case '/':
                e=L.a[L.top-1]/L.a[L.top];
                break;
            }
            L.a[L.top-1]=e;                                          //往前一位存储
            L.a[L.top]=0;
            L.top--;
        }
    }
    printf("%.0lf",L.a[L.top]);                                    //输出最后结果
    return 0;
}

 

  • 17
    点赞
  • 109
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wmsofts

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值