数据结构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;
}

 

以下是利用中缀表达式换成后缀表达式进行运算的C语言代码: ```c #include <stdio.h> #include <stdlib.h> #include <ctype.h> typedef struct stack_node { char data; struct stack_node *next; } stack_node; typedef struct { stack_node *top; } stack; stack *create_stack() { stack *s = (stack *)malloc(sizeof(stack)); s->top = NULL; return s; } void push(stack *s, char c) { stack_node *node = (stack_node *)malloc(sizeof(stack_node)); node->data = c; node->next = s->top; s->top = node; } char pop(stack *s) { if (s->top == NULL) { printf("Error: stack is empty\n"); exit(1); } char c = s->top->data; stack_node *temp = s->top; s->top = s->top->next; free(temp); return c; } char peek(stack *s) { if (s->top == NULL) { printf("Error: stack is empty\n"); exit(1); } return s->top->data; } int is_empty(stack *s) { return (s->top == NULL); } int is_operator(char c) { return (c == '+' || c == '-' || c == '*' || c == '/'); } int precedence(char c) { switch (c) { case '+': case '-': return 1; case '*': case '/': return 2; default: return 0; } } char *infix_to_postfix(char *infix) { stack *s = create_stack(); char *postfix = (char *)malloc(sizeof(char) * (strlen(infix) + 1)); int i, j; for (i = 0, j = 0; infix[i] != '\0'; i++) { if (isdigit(infix[i])) { postfix[j++] = infix[i]; } else if (is_operator(infix[i])) { while (!is_empty(s) && is_operator(peek(s)) && precedence(peek(s)) >= precedence(infix[i])) { postfix[j++] = pop(s); } push(s, infix[i]); } else if (infix[i] == '(') { push(s, infix[i]); } else if (infix[i] == ')') { while (!is_empty(s) && peek(s) != '(') { postfix[j++] = pop(s); } if (is_empty(s)) { printf("Error: mismatched parentheses\n"); exit(1); } pop(s); } else { printf("Error: invalid character\n"); exit(1); } } while (!is_empty(s)) { if (peek(s) == '(') { printf("Error: mismatched parentheses\n"); exit(1); } postfix[j++] = pop(s); } postfix[j] = '\0'; return postfix; } int evaluate_postfix(char *postfix) { stack *s = create_stack(); int i, operand1, operand2, result; for (i = 0; postfix[i] != '\0'; i++) { if (isdigit(postfix[i])) { push(s, postfix[i] - '0'); } else if (is_operator(postfix[i])) { operand2 = pop(s); operand1 = pop(s); switch (postfix[i]) { case '+': result = operand1 + operand2; break; case '-': result = operand1 - operand2; break; case '*': result = operand1 * operand2; break; case '/': if (operand2 == 0) { printf("Error: division by zero\n"); exit(1); } result = operand1 / operand2; break; } push(s, result); } else { printf("Error: invalid character\n"); exit(1); } } result = pop(s); if (!is_empty(s)) { printf("Error: invalid expression\n"); exit(1); } return result; } int main() { char infix[100], *postfix; int result; printf("Enter an infix expression: "); scanf("%s", infix); postfix = infix_to_postfix(infix); printf("Postfix expression: %s\n", postfix); result = evaluate_postfix(postfix); printf("Result: %d\n", result); free(postfix); return 0; } ``` 该程序中,`stack_node`结构体表示中的节点,包含一个字符类型的数据`data`和一个指向下一个节点的指针`next`。`stack`结构体表示,包含一个指向顶节点的指针`top`。`create_stack`函数用于创建一个空,`push`函数用于将一个字符压入中,`pop`函数用于弹出顶字符,`peek`函数用于获取顶字符而不弹出,`is_empty`函数用于判断是否为空。 `is_operator`函数用于判断一个字符是否为运算符,`precedence`函数用于获取运算符的优先级。`infix_to_postfix`函数用于将中缀表达式换成后缀表达式,采用经典的算法:从左到右遍历中缀表达式,如果是数字直接输出到后缀表达式中,如果是左括号,如果是右括号则弹出中的元素直到遇到左括号,如果是运算符则弹出中优先级大于等于它的元素并输出到后缀表达式中,然后将自己入。最后将中剩余的元素弹出并输出到后缀表达式中。在换过程中需要处理一些错误情况,如不合法的字符、不匹配的括号等。 `evaluate_postfix`函数用于计算后缀表达式的值,也是采用经典的算法:从左到右遍历后缀表达式,如果是数字则入,如果是运算符则弹出中的两个操作数进行运算,并将结果入。最后中剩下的元素就是表达式的值。 在`main`函数中,首先读入中缀表达式,然后调用`infix_to_postfix`函数将其换成后缀表达式,并输出后缀表达式。接着调用`evaluate_postfix`函数计算后缀表达式的值,并输出结果。最后释放动态分配的内存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

wmsofts

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

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

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

打赏作者

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

抵扣说明:

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

余额充值