【C语言】利用‘后缀表达式‘求解‘中缀表达式‘

一名大一初学狗,最近在学习栈的应用,在此记录解题代码:

** 题目描述 **
给出一个表达式,其中运算符仅包含+,-,*,/,^要求求出表达式的最终值 ,数据可能会出现括号情况, 还有可能出现多余括号情况 ,数据保证不会出现> maxlongint的数据 ,数据可能回出现负数情况

输入
仅一行,即为表达式

输出
仅一行,既为表达式算出的结果

样例输入

c (2+2)^(1+1)

样例输出

16

解题思路:
将中缀表达式转换成后缀表达式–>计算后缀表达式的值–>得出结果

转换成后缀表达式

第一步:建立两个栈number、symbol,分别用来存储后缀表达式,转换过程中运算符存储的空间。

第二步:依次对数据(给定的中缀表达式)进行操作:

  • 遇到数字时,直接将数字压入number栈

  • 遇到运算符时(包括对负数的处理):

    若为 ( ,首先检测数据是否是负数,负数格式为(-x),检测下一位数据,若为-,则判定x为负数,进行相关操作。否则,直接将 ( 入symbol栈。

    若为**)**:出栈所有运算符,并依次压入number栈,直到遇到 (,最后将 **(**出栈。

    若为 ±*/^ ,首先判断此运算符的优先级是否大于symbol栈栈顶运算符,是则直接入symbol栈,
    否则,symbol栈栈顶运算符出栈,随后压入number栈。再将此运算符入symbol栈,再与前一位运算符比较,重复上述操作,直到symbol栈栈顶运算符的优先级大于前一位运算符。

  • 当数据都操作完后,出栈symbol栈中所有的运算符,依次压入number栈。

以 (2+2)^(1+1) -(-100) * 4/2 为例,结果为 2 2 + 1 1 + ^ -100 4 * 2 / -

后缀表达式的运算
建立一个新栈answer,扫描number栈,遇到数字就直接压入answer栈,遇到运算符,则取出answer栈栈顶的两个数字进行相应计算,运算的结果再入栈,直到扫描完,此时answer栈只剩下一个数值,即为最终结果。

以 2 2 + 1 1 + ^ -100 4 * 2 / - 为例

+——>2+2=4,+——>1+1=2,^ ——>4^2=16,* ——> (-100)*4=(-400),

/ ——>(-400)/2=(-200), – ——> 16-(-200)=216。

代码如下:

#include <stdio.h>

int flag;

struct Symbol
{
	int top;
	char s[100];
}symbol;

struct Number
{
	int top;
	char n[100];
}number;

struct Answer
{
	int top;
	int a[100];
}answer;

void init()
{
	symbol.top = -1;
	number.top = -1;
	answer.top = -1;
}

//将运算符替换成数字以比较优先级
int replace(char a)
{
	switch (a)
	{
	case '+':return 1;
	case '-':return 1;
	case '*':return 2;
	case '/':return 2;
	case '^':return 3;
	case '(':return 0;
	case ')':return 0;
	}
}

//比较符号优先级
int compare(char s, char e)
{
	return (replace(s) < replace(e)) ? 1 : 0;
}

//^运算符的计算操作
void fun()
{
	if (answer.a[answer.top] == 0) { answer.a[answer.top - 1] = 1; return; }
	int t = answer.a[answer.top - 1];
	while (--answer.a[answer.top])
	{
		answer.a[answer.top - 1] *= t;
	}
}

//符号计算操作
void Priority(int i)
{
	switch (number.n[i])
	{
	case '*':answer.a[answer.top - 1] = answer.a[answer.top - 1] * answer.a[answer.top]; break;
	case '/':
		answer.a[answer.top - 1] = answer.a[answer.top - 1] / answer.a[answer.top];
		break;
	case '+':answer.a[answer.top - 1] = answer.a[answer.top - 1] + answer.a[answer.top]; break;
	case '-':answer.a[answer.top - 1] = answer.a[answer.top - 1] - answer.a[answer.top]; break;
	case '^':fun(); break;
	}
	answer.top--;
}


//转换为逆波兰(后缀)表达式
void reversePolish(char ex[])
{
	for (int i = 0; ex[i] != '\0'; i++)
	{
		if (ex[i] <= '9' && ex[i] >= '0')
		{
			if (flag == 1) {
				number.n[++number.top] = '-';
			}
			number.n[++number.top] = ex[i];
			for (int m = i + 1; ex[m] <= '9' && ex[m] >= '0'; i++, m++)
			{
				number.n[++number.top] = ex[m];
			}
		}

		else
		{
			if (symbol.top == -1&&flag==0)
			{
				if (ex[i] == '(')
				{
					if (ex[i + 1] == '-') {
						i++; flag = 1; continue;
					}
				}
				symbol.s[++symbol.top] = ex[i]; continue;
			}
			if (ex[i] == '(')
			{
				if (ex[i + 1] == '-')
				{
					i++; flag = 1; continue;
				}
				symbol.s[++symbol.top] = ex[i]; continue;
			}
			if (ex[i] == ')')
			{
				if (flag == 1) {
					flag = 0; continue;
				}
				while (symbol.s[symbol.top] != '(')
				{
					number.n[++number.top] = symbol.s[symbol.top];
					symbol.top--;
				}
				symbol.top--;
				continue;
			}
			if (compare(symbol.s[symbol.top], ex[i])) symbol.s[++symbol.top] = ex[i];
			else
			{
				number.n[++number.top] = symbol.s[symbol.top];
				symbol.s[symbol.top] = ex[i];
				while (!compare(symbol.s[symbol.top - 1], symbol.s[symbol.top]) && symbol.top > 0)
				{
					number.n[++number.top] = symbol.s[symbol.top - 1];
					symbol.s[symbol.top - 1] = symbol.s[symbol.top];
					symbol.top--;
				}
			}
		}
		number.n[++number.top] = ' ';
	}

	while (symbol.top != -1)
	{
		if (symbol.s[symbol.top] == '(' || symbol.s[symbol.top] == ')') {
			symbol.top--; continue;
		}
		number.n[++number.top] = symbol.s[symbol.top];
		symbol.top--;
	}
}

//逆波兰(后缀)表达式计算
void calculation()
{
	int t = 0;
	for (int i = 0; i <= number.top; i++)
	{
		if (number.n[i] == ' ') continue;
		if (number.n[i] == '-'&& number.n[i+1] <= '9' && number.n[i+1] >= '0') { t = 1; continue;  }
		if (number.n[i] <= '9' && number.n[i] >= '0')
		{
			answer.a[++answer.top] = number.n[i] - '0';
			for (int m = i + 1; number.n[m] <= '9' && number.n[m] >= '0'; i++, m++)
			{
				answer.a[answer.top] = answer.a[answer.top] * 10 + (number.n[m] - '0');
			}
			if (t == 1)
			{
				answer.a[answer.top] *= (-1); t = 0;
			}
		}
		else
		{
			Priority(i);
		}
	}
	printf("%d\n", answer.a[answer.top]);
}

int main() {
	char ex[40];
	int flag = 0;
	init();
	gets(ex);
	reversePolish(ex);
	calculation();

	return 0;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值