算法思想:
- 规定运算符的优先级表
- 设置两个栈,运算数栈,运算符栈。
输入一个表达式,自左向右扫描,进行如下处理:若遇到运算数则进栈,若遇到运算符,则与运算符栈中的栈顶元素进行优先级比较。1.如果当前运算符优先级大于栈顶元素的优先级,则当前运算符进栈。2.如果当前运算符的优先级小于等于栈顶元素的优先级,则运算符栈退栈一次,运算数栈退栈两次,得到运算数a和运算数b和运算符op,执行运算后将得到的结果压进运算数栈。
先是两个头文件:
NumLinkStack.h
#include<stdio.h>
#include<stdlib.h>
typedef struct Node1
{
int data;
struct Node1 *next;
}NumNode, *NumStack;
int NumInitStack(NumStack *L)
{
(*L) = (NumNode *)malloc(sizeof(NumNode));
if (!(*L))
{
return 0;
}
else
{
(*L)->next = NULL;
return 1;
}
}
int NumPush(NumStack L,int x)
{
NumNode *temp;
temp = (NumNode *)malloc(sizeof(NumNode));
if (!temp)
{
return 0;
}
temp->data = x;
temp->next = L->next;
L->next = temp;
return 1;
}
int NumPop(NumStack L, int *x)
{
NumNode *temp;
temp = L->next;
if (temp==NULL)
{
return 0;
}
*x = temp->data;
L->next = temp->next;
free(temp);
return 1;
}
int NumGetTop(NumStack L)
{
if (L->next==NULL)
{
return 0;
}
else
{
return L->next->data;
}
}
OperaLinkStack.h
#include<stdio.h>
#include<stdlib.h>
typedef struct Node2
{
char data;
struct Node2 *next;
}OperaNode, *OperaStack;
int OperaInitStack(OperaStack *L)
{
(*L) = (OperaNode *)malloc(sizeof(OperaNode));
if (!(*L))
{
return 0;
}
else
{
(*L)->next = NULL;
return 1;
}
}
int OperaPush(OperaStack L, char x)
{
OperaNode *temp;
temp = (OperaNode *)malloc(sizeof(OperaNode));
if (!temp)
{
return 0;
}
temp->data = x;
temp->next = L->next;
L->next = temp;
return 1;
}
int OperaPop(OperaStack L, char *x)
{
OperaNode *temp;
temp = L->next;
if (temp == NULL)
{
return 0;
}
*x = temp->data;
L->next = temp->next;
free(temp);
return 1;
}
char OperaGetTop(OperaStack L)
{
if (L->next==NULL)
{
return 0;
}
else
{
return L->next->data;
}
}
主函数:
#include "NumLinkStack.h"
#include "OperaLinkStack.h"
#include <math.h>
#include <string.h>
int ExpEvaluation(NumStack N, OperaStack L);//计算函数
int Judege(char ch);//判断是否为运算符
char Compare(char ch, char ch2);//判断运算符的优先级
int Execute(int a, char op, int b);//运算
int main(void)
{
NumStack N;
OperaStack L;
NumInitStack(&N);
OperaInitStack(&L);
printf("%d",ExpEvaluation(N, L));
getchar();
getchar();
return 0;
}
int ExpEvaluation(NumStack N, OperaStack L)
{
char express[100];
int i = 0;
int k = 0;
int j = 0;
int num2 = 0;
char e;
int a, b;
char op;
OperaPush(L, '=');
printf("Please input an expresion (Ending with =)\n");
scanf("%s",express);
while (express[i] != '='|| OperaGetTop(L) != '=')
{
if (express[i] >= '0'&&express[i] <= '9')
{
k++;
if (k<=j)//判断此时为几位数,如果j大于k时,表明前面的为运算符,num2从个位开始相加,故num2不用归零了
{
num2 = express[i] - 48;
i++;
}
if (k>j)
{
num2 = num2 * 10 + (express[i] - 48);
k = j = 0;
i++;
}
if (!Judege(express[i]))//如果后面的数还是运算数的话,k++
{
k++;
}
if (k==j)//表明后面的为运算符了,将前面的数字压栈
{
NumPush(N, num2);
}
}
else if (Judege(express[i]))
{
switch (Compare(express[i], OperaGetTop(L)))
{
case '<':
OperaPush(L, express[i++]);
if (express[i] != '('&&express[i] != ')')//当运算符为括号时,不进行j++操作例23+(56*5)
j++;
break;
case '=':
OperaPop(L, &e);//脱括号,并接受下一个字符
i++;
break;
case '>':
OperaPop(L, &op);
NumPop(N, &b);
NumPop(N, &a);
NumPush(N, Execute(a, op, b));//注意此处运算结束后,i不加一
break;
}
}
}
return NumGetTop(N);
}
int Judege(char ch)
{
char ptr[8] = { '+', '-', '*', '/', '(', ')', '=' };
int i;
for (i = 0; i < 7; i++)
{
if (ch == ptr[i])
return 1;
}
return 0;
}
char Compare(char a, char b)
{
int i, j;
char Table[8][8] =
{
{ ' ', '+', '-', '*', '/', '(', ')', '=' },
{ '+', '>', '>', '<', '<', '<', '>', '>' },
{ '-', '>', '>', '<', '<', '<', '>', '>' },
{ '*', '>', '>', '>', '>', '<', '>', '>' },
{ '/', '>', '>', '>', '>', '<', '>', '>' },
{ '(', '<', '<', '<', '<', '<', '=', ' ' },
{ ')', '>', '>', '>', '>', ' ', '>', '>' },
{ '=', '<', '<', '<', '<', '<', ' ', '=' }
}; //优先级表格
for (i = 0; i < 8; i++)
if (Table[0][i] == a) //纵坐标寻找
break;
for (j = 0; j < 8; j++) //横坐标寻找
if (Table[j][0] == b)
break;
return Table[j][i];
}
int Execute(int a, char op, int b)
{
switch (op)
{
case '+':return a + b;
case '-':return a - b;
case '*':return a * b;
case '/':return a / b;
}
}