题目:
利用栈编写表达式求值程序:输入含有“ + ”、“ - ”、“ * ”、“ / ”四则运算的表达式,其中负数要用(0 - 正数)表示,并以 = 结束。要求输出表达式的值。
输入格式
第一行:一个算术表达式
输出格式
第一行:算术表达式的值
输入样例
3 * (9 - 7) =
输出样例
6
一、解题思路:
①. 注意栈元素为整型类型。由于表达式的运算符号为字符类型,但依然能够以ASCII码形式储存在栈中,故栈元素可以不用定义为字符类型,而定义为整型类型数据即可,方便从后缀表达式中将字符类型转变为整型类型进行处理,保持了栈元素类型的一致性,方便处理
②. 本代码借用 ‘#’ 分隔数字,故本程序可以处理多位数运算的表达式
步骤一:
中缀表达式:
3 - 10 * ( 9 - 12 ) =
从键盘中输入中缀表达式字符串,创建符号栈operate处理中缀表达式,将其转变为后缀表达式储存在字符串suffix[]中
步骤二:
后缀表达式:
3#10#9#12#-*-
处理后缀表达式字符串:创建数字栈number,遍历后缀表达式,如果是数字,则入栈; 如果是运算符,则出栈两个整型数字a,b,分别作为操作数和被操作数进行运算,把运算结果入栈; 后缀表达式遍历结束后,栈中仅存一个元素即为后缀表达式的运算结果
运算结果:
33
二、代码模块:
①、栈的建立基本函数:
#include<malloc.h>
#include<stdio.h>
#include<string.h>
#define OK 1
#define ERROR 0
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量
typedef int SElemType; // 定义栈元素类型
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
struct SqStack
{
SElemType* base; // 在栈构造之前和销毁之后,base的值为NULL
SElemType* top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
}; // 顺序栈
Status InitStack(SqStack& S)
{
// 构造一个空栈S,该栈预定义大小为STACK_INIT_SIZE
S.base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if (!S.base) return ERROR;
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
Status Push(SqStack& S, SElemType e)
{
// 在栈S中插入元素e为新的栈顶元素
if (S.top - S.base >= S.stacksize)
{
S.base = (SElemType*)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
if (!S.base) return ERROR;
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top++ = e;
return OK;
}
Status Pop(SqStack& S, SElemType& e)
{
// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
if (S.top == S.base) return ERROR;
e = *--S.top;
return OK;
}
Status GetTop(SqStack S, SElemType& e)
{
// 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
if (S.top == S.base) return ERROR;
e = *(S.top - 1);
return OK;
}
int StackLength(SqStack S)
{
// 返回栈S的元素个数
int i;
i = S.top - S.base;
return i;
}
Status StackTraverse(SqStack S)
{
// 从栈顶到栈底依次输出栈中的每个元素
SElemType* p = (SElemType*)malloc(sizeof(SElemType));
p = S.top;
if (S.top == S.base)printf("The Stack is Empty!");
else
{
printf("The Stack is: ");
p--;
while (p >= S.base)
{
printf("%d ", *p);
p--;
}
}
printf("\n");
return OK;
}
②、结合主函数中的if分支对中缀表达式的字符判断运算符的优先级:
//比较栈顶符号和当前符号的优先级,如果栈顶符号优先级较高,则一直出栈,最后把当前符号入栈;否则,当前符号入栈
int ComparePriority(SElemType stackTop, SElemType cur)
{
switch (stackTop)
{
case '(':
return 1;
break;
case '+':
case '-':
if (cur == '*' || cur == '/')
return 1;
break;
default:
break;
}
return 0;
}
③、操作数与被操作数的运算:
//运算函数
int Calculate(SElemType ch, int a, int b)
{
int result = 0;
switch (ch)
{
case '+':
result = b + a;
break;
case '-':
result = b - a;
break;
case '*':
result = b * a;
break;
case '/':
result = b / a;
break;
default:
break;
}
return result;
}
④、主函数(包括中缀表达式转化为后缀表达式和后缀表达式的求值):
int main()
{
char s[1000];
gets_s(s,1000);
char suffix[1000];
int index_su = 0;
/*中缀表达式转化为后缀表达式*/
//初始化符号栈,整型元素栈
SqStack operate;
InitStack(operate);
int i;
int e;
for (i = 0; i < strlen(s); i++)
{
if (s[i] >= '0' && s[i] <= '9')//是数字,保存到后缀表达式中
{
suffix[index_su++] = s[i];
if (s[i + 1] < '0' || s[i + 1] > '9')
{
suffix[index_su++] = '#';
}
}
else if (s[i] == ' ' || s[i] == '=')//是空格或等号,忽略
{
continue;
}
else//是运算符号,需要入栈出栈判断处理
{
SElemType top;
GetTop(operate, top);
if (StackLength(operate) == 0 || s[i] == '(')//如果栈为空,或者当前符号为左括号,则入栈
{
Push(operate, s[i]);
}
else if (s[i] == ')')//如果当前符号是右括号,则一直出栈
{
do
{
Pop(operate, e);
if (e != '(')
{
suffix[index_su++] = e;
}
} while (e != '(');
}
else if (ComparePriority(top, s[i]) == 1)//当前符号优先级较高
{
Push(operate, s[i]);
}
else if (ComparePriority(top, s[i]) == 0)//栈顶符号优先级较高
{
do
{
Pop(operate, e);
suffix[index_su++] = e;
GetTop(operate, top);//重新获取栈顶符号
} while (ComparePriority(top, s[i]) == 0 && StackLength(operate) != 0);//当栈中还有符号并且栈顶符号优先级较高时,出栈
Push(operate, s[i]);//当前符号入栈
}
}
}
//把栈中元素全部出栈,保存到后缀表达式中
do
{
Pop(operate, e);
suffix[index_su++] = e;
} while (operate.top > operate.base);
suffix[index_su] = '\0';//结束后缀表达式
puts(suffix);
/*后缀表达式求值*/
//初始化数栈
SqStack number;
InitStack(number);
int num = 0;
for (i = 0; i < strlen(suffix); i++)
{
if (suffix[i] >= '0' && suffix[i] <= '9')
{
while (suffix[i] != '#')
{
num = num * 10 + (suffix[i++] - '0');
}
Push(number, num);
//printf("num = %d\n", num);
num = 0;
}
else
{
int a, b;
Pop(number, a);
Pop(number, b);
int result = Calculate(suffix[i], a, b);
//printf("a = %d, b = %d, result = %d\n", a, b, result);
Push(number, result);
}
}
int result;
Pop(number, result);
printf("%d\n", result);
return 0;
}
有任何问题可以留言交流,我一定及时回复