一名大一初学狗,最近在学习栈的应用,在此记录解题代码:
** 题目描述 **
给出一个表达式,其中运算符仅包含+,-,*,/,^要求求出表达式的最终值 ,数据可能会出现括号情况, 还有可能出现多余括号情况 ,数据保证不会出现> 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;
}