/* run this program using the console pauser or add your own getch, system("pause") or input loop */
// 用到的库文件
#include <stdio.h> // printf();scanf()
#include <stdlib.h> // exit()
#include <malloc.h> // malloc()
#include <time.h> // srand((unsigned)time(NULL));
// 函数结果状态代码
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
// Status是函数的类型,其值是函数结果状态代码
typedef int Status;
// 3.2.5 表达式求值----------------------------------------
// 栈的元素类型
typedef char SElemType;
// -----栈的链式存储结构----------------------------------
typedef struct SNode {
SElemType data; // 数据域
struct SNode *next; // 指针域
} SNode, *LinkStack;
Status visit(SElemType e);
// 操作结果:构造一个空栈S。
Status InitStack(LinkStack &S) {
S = (LinkStack)malloc(sizeof(SNode));
if(!S) // 存储分配失败
exit(OVERFLOW); // exit(-2)程序异常退出
S->next = NULL;
return OK;
}// InitStack
// 操作结果:销毁栈S,S不再存在。
Status DestroyStack(LinkStack &S) {
LinkStack p = S->next, ptmp; // p指向栈顶
while(p) { // p指向栈底时,循环停止
ptmp = p->next;
free(p); // 释放每个数据结点的指针域
p = ptmp;
}
free(S);
return OK;
}// DestroyStack
// 操作结果:把S置为空栈。
Status ClearStack(LinkStack &S) {
LinkStack p = S->next, ptmp; // p指向栈顶
while(p) { // p指向栈底时,循环停止
ptmp = p->next;
free(p); // 释放每个数据结点的指针域
p = ptmp;
}
S->next = NULL;
return OK;
}// ClearStack
// 操作结果:若S为空栈,返回TRUE,否则返回FALSE
Status StackEmpty(LinkStack S) {
if(S->next == NULL)
return TRUE; // 返回1
else
return FALSE; // 返回0
}// StackEmpty
// 操作结果:返回S的元素个数,即栈的长度。
int StackLength(LinkStack S) {
int n = 0;
LinkStack p = S->next; // p指向栈顶
while(p) {
n++;
p = p->next;
}
return n;
}// StackLength
// 操作结果:若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR。
Status GetTop(LinkStack S, SElemType &e) {
if ( S->next == NULL )
return ERROR; // 栈空
e = S->next->data; // 取栈顶元素
// printf("获取的栈顶元素:"); visit(e);
return OK;
}// GetTop
// 操作结果:插入元素e为新的栈顶元素。
Status Push(LinkStack &S, SElemType e) {
LinkStack p = (LinkStack)malloc(sizeof(SNode));
p->data = e;
p->next = S->next; // 新结点指向栈顶
S->next = p; // 更新栈顶指针
// printf("插入的栈顶元素:"); visit(e);
return OK;
}// Push
// 操作结果:若栈不空,则删除S的栈顶元素,并用e返回其值;否则返回ERROR。
Status Pop(LinkStack &S, SElemType &e) {
// 若1个元素也没有:
if (S->next == NULL)
return ERROR;
// 若有1个以上元素
e = S->next->data;
LinkStack ptmp = S->next->next;
free(S->next);
S->next = ptmp;
// printf("删除的栈顶元素:"); visit(e);
return OK;
}// Pop
Status visit(SElemType e) {
printf(" %c\n", e);
return OK;
}
// 操作结果:从 栈底到栈顶 依次对栈中每个数据元素调用函数visit()。一旦vistit()失败,刚操作失败。
Status StackTraverse(LinkStack S, Status (*pfn_visit)(SElemType)) {
if(S->next == NULL)
{
printf("栈为空!\n");
return ERROR;
}
for(int i=StackLength(S); i>0; i--)
{
LinkStack p = S->next; // p指向栈顶
int j = 1; // j为计数器
while ( p && j<i ) { // 顺指针向后查找,直到p指向第i个元素或p为空
p = p->next;
++j;
}
visit(p->data);
}
printf("\n");
return OK;
}// StackTraverse_base_to_Top
// 操作结果:从 栈顶到栈底 依次对栈中每个数据元素调用函数visit()。一旦vistit()失败,刚操作失败。
Status StackTraverse_Top(LinkStack S, Status (*pfn_visit)(SElemType)) {
if(S->next == NULL)
{
printf("栈为空!\n");
return ERROR;
}
LinkStack p = S->next; // p指向栈顶
while(p) {
visit(p->data);
p = p->next;
}
printf("\n");
return OK;
}// StackTraverse_Top_to_base
// 3.2.5 表达式求值----------------------------------------
// 判定运算符栈的(栈顶运算符θ1)与(读入的运算符θ2)之间的优先关系
SElemType Precede(SElemType t1, SElemType t2)
{
SElemType t;
switch (t1)
{
case '+':
case '-':
if(t2=='*' || t2=='/' || t2=='(')
t = '<';
else t = '>';
break;
case '*':
case '/':
if(t2 == '(')
t = '<';
else t = '>';
break;
case '(':
if(t2 == ')')
t = '=';
else if(t2 == '#')
return ERROR;
else t = '<';
break;
case ')':
if(t2 == '(')
return ERROR;
else t = '>';
break;
case '#':
if(t2 == ')')
return ERROR;
else if(t2 == '#')
t = '=';
else t = '<';
break;
}
return t;
}
// 进行二元运算 a θ b
SElemType Operator(SElemType a, SElemType theta, SElemType b)
{ //
SElemType ret;
switch(theta)
{
case '+':
ret = (a-48) + (b-48) + 48;
break;
case '-':
ret = (a-48) - (b-48) + 48;
break;
case '*':
ret = (a-48) * (b-48) + 48;
break;
case '/':
ret = (a-48) / (b-48) + 48;
break;
}
return ret;
}
Status In(SElemType c)
{ //
switch(c)
{
case '+':
case '-':
case '*':
case '/':
case '(':
case ')':
case '#':
case '=':
return TRUE;
break;
default:
return FALSE;
}
}
typedef char OperandType;
OperandType ExvaluateExpression()
{ // 算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合。
LinkStack OPTR; // 运算符栈:寄存运算符
LinkStack OPND; // 运算数栈:寄存操作数或运算结果
char c, x, theta, a, b, e;
InitStack(OPTR);
InitStack(OPND);
Push(OPTR, '#'); // 表达式起始符“#”为运算符栈的栈底元素
printf("输入表达式:\n");
c = getchar();
GetTop(OPTR, e);
while (c!='#' || e!='#') // 当前读入的字符 或 运算符栈顶元素不为‘#’号
{
if (!In(c)) // 不是运算符(操作数、结果)则进栈
{
Push(OPND, c);
c = getchar();
}
else // 是运算符,则和运算符栈顶的运算符比较优先级
{
GetTop(OPTR, e);
switch (Precede(e, c))
{
case '<': // 栈顶元素优先权低
Push(OPTR, c);
c = getchar();
break;
case '=': // 脱括号并接收下一字符
Pop(OPTR, x);
c = getchar();
break;
case '>': // 退栈并将运算结果入栈
Pop(OPTR, theta);
Pop(OPND, b);
Pop(OPND, a);
Push(OPND, Operator(a, theta, b));
break;
}// switch
}// else
GetTop(OPTR, e);
}// while
GetTop(OPND, e);
return e;
}// EvaluateExpression 算法3.4
int main()
{
// 3*(7-2)#=15
char c;
do {
fflush(stdin);
c = ExvaluateExpression();
printf("表达式的值:");
printf("%d\n", c-48);
printf("是否继续(y/n):");
} while(scanf("%s", &c)!=0 && (c=='y' || c=='Y'));
return 0;
}
《数据结构》(C语言版)——栈的应用举例-表达式求值
最新推荐文章于 2019-01-08 02:47:04 发布