棧之計算表示式值
阿新 • • 發佈:2019-02-05
演算法思想:
- 規定運算子的優先順序表
- 設定兩個棧,運算數棧,運算子棧。
輸入一個表示式,自左向右掃描,進行如下處理:若遇到運算數則進棧,若遇到運算子,則與運算子棧中的棧頂元素進行優先順序比較。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;
}
}