数据结构系列:表达式求值
——————————————————————————
算法思想:
该算法在读入用户输入的中缀表达式后,直接对其进行计算。算法的基本流程如下:首先建立两个栈OPTR(操作符栈)和OPND(操作数栈),分别用于存放操作符和操作数,然后对用户输入的表达式进行扫描。如果遇到数字,就将其压入数值栈OPND,并读入表达式的下一个字符;如果遇到操作符,则比较操作符栈OPTR栈顶的操作符与当前索引下的操作符的优先级,并根据比较结果做出不同的操作:
若栈顶操作符的优先级低于当前索引下的操作符,则将当前索引下的操作符压入操作符栈OPTR,并读入表达式的下一个字符;
若栈顶操作符与当前索引下的操作符优先级相同,则将栈顶操作符弹出,并读入表达式的下一个字符;
若栈顶操作符的优先级高于当前索引下的操作符,则取出栈顶操作符
,并从数值栈OPND中依次取出操作数
、
,计算表达式
的值,并将结果压入数值栈
中。
重复进行上述操作,直到读取到表达式的结束标记并且操作符栈OPTR为空,此时数值栈
中存放的数值即为表达式计算的最终结果。*
——————————————————————————
算法流程图:
应该能看懂吧,看不懂的话应该是数据结构没好好听课了。
——————————————————————————
第二步:话不多说放代码
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define Stack_increment 20
#define Stack_Size 100
/*运算符数组*/
char ops[7] = { '+', '-', '*', '/', '(', ')', '#' };
/*用来进行比较运算符优先级的矩阵,3代表'=',2代表'>',1代表'<',0代表不可比*/
int cmp[7][7] = { { 2, 2, 2, 2, 2, 1, 1 },
{ 2, 2, 2, 2, 2, 1, 1 },
{ 1, 1, 2, 2, 2, 1, 1 },
{ 1, 1, 2, 2, 2, 1, 1 },
{ 2, 2, 2, 2, 3, 1, 0 },
{ 1, 1, 1, 1, 0, 1, 1 },
{ 2, 2, 2, 2, 2, 0, 3 } };
/*运算符栈的定义*/
typedef struct
{
int stacksize;
int *top;
int *base;
}SeqStack;
/* 运算数栈的定义*/
typedef struct
{
int stacksize;
int *top;
int *base;
}numSeqStack;
/*初始化运算符栈*/
void InitStack(SeqStack *S)
{
S->base = (int *)malloc(Stack_Size * sizeof(int));
S->top = S->base;
S->stacksize = Stack_Size;
}
/*初始化运算数栈*/
void InitStacknum(numSeqStack *S)
{
S->base = (int *)malloc(Stack_Size * sizeof(int));
S->top = S->base;
S->stacksize = Stack_Size;
}
/*判操作符栈为空栈时返回值为真,反之为假*/
int IsEmpty(SeqStack *S)
{
return(S->top == S->base ? 1 : 0);
}
/*判断栈S为空栈时返回值为真,反之为假*/
int IsEmptynum(numSeqStack *S)
{
return(S->top == S->base ? 1 : 0);
}
/*判断符号栈S为满栈时返回值为真,反之为假*/
int IsFull(SeqStack *S)
{
return (*S->top == Stack_Size - 1 ? 1 : 0);
}
/*判断操作数栈为满栈时返回值为真,反之为假*/
int IsFullnum(numSeqStack *S)
{
return (*S->top == Stack_Size - 1 ? 1 : 0);
}
/*运算符栈入栈函数, '#'为结束标志*/
void Push(SeqStack *S, char x)
{
if (* (S -> top) == Stack_Size - 1)
{
printf("Stack is full\n");
S->base = (int *)realloc(S->base, (S->stacksize + Stack_increment) * sizeof(int));
S->top = S->base + S->stacksize;
S->stacksize = S->stacksize + Stack_increment;
}
else if (x == '#')
{
return;
}
else
{
*S->top++ = x;
}
}
/*运算数入栈函数*/
void Pushnum(numSeqStack *S, int x)
{
if (*S->top == Stack_Size - 1)
{
S->base = (int *)realloc(S->base, (S->stacksize + Stack_increment) * sizeof(int));
S->top = S->base + S->stacksize;
S->stacksize = S->stacksize + Stack_increment;
}
else if ((char)x == '#')
{
return;
}
else
{
*(S -> top) = x;
S -> top++;
}
}
/*运算符栈出栈函数*/
int Pop(SeqStack *S)
{
if (S->top == S->base)
{
return 0;
}
else
{
--(S->top);
return 1;
}
}
/*运算数栈出栈函数*/
int Popnum(numSeqStack *S)
{
if (S -> top == S -> base)
{
return 0;
}
else
{
--(S -> top);
return 1;
}
}
/*运算符栈取栈顶元素函数*/
char GetTop(SeqStack *S)
{
return (*(S->top - 1));
}
/*运算数栈取栈顶元素函数*/
int GetTopnum(numSeqStack *S)
{
if (S -> top == S -> base)
{
return (*(S -> top ));
}
return (* (S -> top - 1));
}
int Isoperator(char ch) /*判断输入字符是否为运算符函数,是返回TRUE,不是返回FALSE*/
{
int i;
for (i = 0; i < 7; i++)
{
if (ch == ops[i])
return (int)1;
}
return (int)0;
}
/*比较运算符优先级函数*/
/*保存优先级比较后的结果'>'、'<'、'='*/
char Compare(char ch1, char ch2)
{
int i, m = 0, n = 0;
int priority;
for (i = 0; i < 7; i++)
{
if (ch1 == ops[i])
m = i;
if (ch2 == ops[i])
n = i;
}
priority = cmp[m][n];
switch (cmp[m][n])
{
case 1:
return (char)('<');
case 2:
return (char)('>');
case 3:
return (char)('=');
default:
printf("表达式错误!\n");
break;
}
}
/*运算函数*/
int Execute(int a, char op, int b)
{
switch (op)
{
case '+':
return (b + a);
break;
case '-':
return (b - a);
break;
case '*':
return (b * a);
break;
case '/':
return (b / a);
break;
}
}
/*读入一个简单算术表达式并计算其值。optr和operand分别为运算符栈和运算数栈,OPS为运算符集合*/
int ExpEvaluation()
{
int a, b, v;
int sum = 0;
char ch, op, temp;
char str[100];
numSeqStack operand;
SeqStack optr;
/*初始化,没有元素*/
InitStack(&optr);
InitStacknum(&operand);
printf("请输入表达式(#为结束符):\n"); /*表达式输入*/
scanf_s("%s", str, 100); /*取得一行表达式至字符串中*/
int i = 0;
for (i; i < (strlen(str) + 1); )
{
ch = str[i];
if (ch == '#')
{
if (IsEmpty(&optr))
{
v = GetTopnum(&operand);
return v;
}
else
{
a = GetTopnum(&operand);
Popnum(&operand);
b = GetTopnum(&operand);
Popnum(&operand);
op = GetTop(&optr);
Pop(&optr);
v = Execute(a, op, b);
Pushnum(&operand, v);
if (ch == ')')
{
Pop(&optr);
}
}
}
else if (!Isoperator(ch))
{
int dis = 0;
int j = i, j1 = i, j2 = i, j3 = i;
int k; /*记录原始值*/
for (k = i; k < (strlen(str) + 1); )
{
if (!Isoperator(ch))
{
i++;
ch = str[i];
k++;
dis = i - j; /*记录差距的位数*/
j1 = i;
j2 = i;
j3 = i;
}
else if (Isoperator(ch))
{
break;
}
}
for (j1 = j1 - dis; j1 < j2 ; j1++)
{
int temp;
temp = (int)(str[j1] - '0');
sum = sum + temp * pow(10, (j2 - j1 - 1)); /*求和*/
if (j2 - j1 < 0)
{
break;
}
}
Pushnum(&operand, sum);
sum = 0;
dis = 0;
}
else if (Isoperator(ch))
{
if (optr.base == optr.top)
{
Push(&optr, ch);
i++;
}
else
{
char buf ;
temp = GetTop(&optr);
buf = Compare(temp, ch);
if (buf == '>')
{
Push(&optr, ch);
i++;
}
else if (buf == '=')
{
Pop(&optr);
}
else
{
a = GetTopnum(&operand);
Popnum(&operand);
b = GetTopnum(&operand);
Popnum(&operand);
op = GetTop(&optr);
Pop(&optr);
v = Execute(a, op, b);
Pushnum(&operand, v);
if (ch == ')')
{
Pop(&optr);
}
else
{
Push(&optr, ch);
}
i++;
}
}
}
}
}
/*主函数*/
int main()
{
int result = 0;
result = ExpEvaluation();
printf("\n表达式结果是%d\n", result);
getchar();
getchar();
return 0;
}
——————————————————————————
三:程序运行展示
四:结语
等老师留了递归非递归遍历二叉树的作业,在继续放程序