中缀表达式转后缀表达式

中缀表达式转后缀表达式:

假定有中缀表达式1 + (( 2 + 3)* 4 ) – 5,请将它转化为后缀表达式。

方法一:利用表达式树

首先将中缀表达式转换为表达式树,然后后序遍历表达式树,所得结果就是后缀表达式。

将中缀表达式转化为表达式树方法:表达式树的树叶是操作数,而其他的节点为操作符,根节点为优先级最低且靠右的操作符(如上述表达式优先级最低的是- 和+,但 + 更靠右,所以根为+),圆括号不包括。如上述中缀表达式转换后的表达式树如下:

在这里插入图片描述

经过后序遍历表达式树后得到的后缀表达式为:12 3 + 4 * + 5 -

方法二:利用辅助栈

从左到右遍历中缀表达式的每个操作数和操作符。当读到操作数时,立即把它输出,即成为后缀表达式的一部分;若读到操作符,判断该符号与栈顶符号的优先级,若该符号优先级高于栈顶元素,则将该操作符入栈,否则就一次把栈中运算符弹出并加到后缀表达式尾端,直到遇到优先级低于该操作符的栈元素,然后把该操作符压入栈中。如果遇到”(”,直接压入栈中,如果遇到一个”)”,那么就将栈元素弹出并加到后缀表达式尾端,但左右括号并不输出。最后,如果读到中缀表达式的尾端,将栈元素依次完全弹出并加到后缀表达式尾端。

在这里插入图片描述
利用辅助栈后缀表达式与用表达式树的结果一样,都为:1 2 3 + 4 * + 5 –

以上内容转载自:https://blog.csdn.net/walkerkalr/article/details/22798365
下面是方法二的C语言代码实现:

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define MAXSIZE 100

//顺序栈的存储定义
typedef struct stack
{
	char *base;//栈底指针
	char *top;//栈顶指针
	int stacksize;//栈分配的存储空间大小
}SqStack;

typedef struct stack2
{
	int *base;//栈底指针
	int *top;//栈顶指针
	int stacksize;//栈分配的存储空间大小
}SqStack2;

SqStack op;//顺序栈op用来存储运算符
SqStack2 st;//st用来存放数值

void Menu();
void InitStack();
void trans(char str[], char rpn[]);
int value(char rpn[]);
int Match(char *p);
//*****************************************************************************
void Menu()
{//界面函数
	printf("*********表达式求值(只能包含+、-、*、/、()和正整数)********* ******\n");
	printf("请选择:1.输入表达式 2.括号匹配检查 3.转换后缀表达式 4.表达式计算5.退出\n");
}
//*****************************************************************************
void InitStack()
{//初始化栈op、st
	op.base = op.top = (char *)malloc(MAXSIZE * sizeof(char));
	if (op.base == NULL) exit(-2);
	st.base = st.top = (int *)malloc(MAXSIZE * sizeof(int));
	if (st.base == NULL) exit(-2);
	op.stacksize = st.stacksize = MAXSIZE;
}
//*****************************************************************************
int Match(char *p)
{//检查表达式中小括号是否匹配
	int flag = 0;
	SqStack s;

	s.base = s.top = (char*)malloc(MAXSIZE * sizeof(char));
	if (!s.base) exit(-2);
	s.stacksize = MAXSIZE;
	while (*p != '\0')
	{
		if (*p == '(')
		{
			if (s.top - s.base == s.stacksize) exit(-1);
			else {
				*s.top = *p;
				s.top++;//将所有的左括号入栈
			}
		}
		if (*p == ')')
		{
			if (s.top != s.base&&*(s.top - 1) == '(') {
				s.top--;
				flag = 1;
			}
			else flag = 2;
		}
		p++;
	}//while
	if ((flag == 1 || flag == 0) && s.top == s.base)
	{
		s.top = s.base;//将栈清空
		return 1;
	}
	else if (flag == 2) {
		s.top = s.base;//将栈清空
		return 0;
	}
}//Match	
//*****************************************************************************
void trans(char str[], char rpn[])
{//将中缀表达式转换为后缀表达式
	char ch;
	int i = 0, t = 0;
	ch = str[i];
	i++;
	while (ch != '\0')
	{
		switch (ch)
		{
		case '(': *op.top++ = ch; break;
		case ')': 
			while (*(op.top - 1) != '(')
			{
				rpn[t] = *(op.top - 1);
				op.top--;
				t++;
			}
			op.top--;//此处必须再次进行--运算,才能忽略已经进入的'(' 
			break;
		case '+':
		case '-':
			while (op.top != op.base && *(op.top - 1) != '(')
			{
				rpn[t] = *(op.top - 1);
				op.top--;
				t++;
			}
			*op.top++ = ch;
			break;
		case '*':
		case '/':
			while (*(op.top - 1) == '*' || *(op.top - 1) == '/')
			{
				rpn[t] = *(op.top - 1);
				op.top--;
				t++;
			}
			*op.top++ = ch;
			break;
		case ' ':break;
		default:
			while (ch >= '0'&&ch <= '9')
			{
				rpn[t] = ch;
				t++;
				ch = str[i];
				i++;
			}
			i--;
			rpn[t] = '#'; t++;
		}//switch
		ch = str[i];
		i++;
	}//while
	while (op.top != op.base)
	{
		rpn[t] = *(op.top - 1);
		t++;
		op.top--;
	}//while
	rpn[t] = '\0';
}//trans
//*****************************************************************************
int value(char rpn[])
{//后缀表达式求值
	int d;
	char ch;
	int t = 0;

	ch = rpn[t];
	t++;
	while (ch != '\0')
	{
		switch (ch)
		{
		case '+':
			*(st.top - 2) = *(st.top - 2) + *(st.top - 1);
			st.top--;
			break;
		case '-':
			*(st.top - 2) = *(st.top - 2) - *(st.top - 1);
			st.top--;
			break;
		case '*':
			*(st.top - 2) = *(st.top - 2) * *(st.top - 1);
			st.top--;
			break;
		case '/':
			if (*(st.top - 1) != 0)
				*(st.top - 2) = *(st.top - 2) / *(st.top - 1);
			else
			{
				printf("\n除0错误!\n");
				exit(0);
			}
			st.top--;
			break;
		default:
			d = 0;
			while (ch >= '0'&&ch <= '9')
			{
				d = 10 * d + ch - '0';
				ch = rpn[t];
				t++;
			}
			*(st.top++) = d;
		}//switch
		ch = rpn[t]; t++;

	}//while
	return *(st.top - 1);
}//value
//*****************************************************************************
int main()
{//主函数
	char str[MAXSIZE], rpn[MAXSIZE], g, f;
	//str数组用来存储接收到的字符串,rpn用来存放转换出来的后缀表达式
	int i, j = 0;
	InitStack();
	Menu();

	while (1)
	{
		scanf("%d", &g);
		switch (g)
		{
		case 1: printf("请输入表达式:");
			scanf("%s", str);
			i = Match(str);
			break;
		case 2: if (i == 1) printf("匹配成功!\n");
				else printf("匹配失败!\n");
			break;
		case 3: if (i == 1)
		{
			trans(str, rpn);
			printf("后缀表达式为:%s\n", rpn);
			j = 1;
		}
				else { j = 0; printf("表达式中括号匹配错误!\n"); }
				break;
		case 4: if (j) printf("计算结果为:%d\n", value(rpn));
				else printf("后缀表达式转换遇到问题!\n");
			break;
		case 5: printf("确定要退出系统吗?(y/n)\n");
			getchar(); f = getchar();
			if (f == 'y' || f == 'Y') exit(0);
			else { printf("请重新选择!\n"); break; }
		default:printf("输入错误!\n");
			exit(1);
		}//switch
	}//while
	return 0;
}//main

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值