1. 程式人生 > >表達式求值(無括號)

表達式求值(無括號)

code ESS truct alc expr 計算 利用 一個 一次

對於自然數的表達式求值,操作有加、減、乘、除和冪運算,分別用+,-, *, /,^來表示,為方便運算,加入#運算符,其運算優先級最低,由於運算符優先級不一樣,可以利用棧實現此操作。

算法思想

(1)規定運算符的優先級表

(2)設置兩個棧:OVS(運算數棧)和OPTR(運算符棧),為了操作方便可以先在OPTR棧中先放一個#運算符

(3)自左向右掃描,進行如下處理:

若遇到運算數則金OVS棧;若遇到運算符則與OPTR棧頂運算符進行比較:

?如果當前運算符的優先級大於OPTR棧頂運算符的優先級,則當前運算符進入OPTR棧;

?如果當前運算符的優先級大於等於OPTR棧頂運算符的優先級,則OPTR退棧一次,得到棧頂運算符op, 連續退棧OVS兩次,得到運算數a和b,執行op運算,得到結果T,將T進OVS棧。

可以自己畫一個表達式兩個棧的變化圖,有助於理解

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<stdbool.h>

typedef struct node{
    int data;//無論對於運算符還是運算數,都用int型變量來保存 
    node *next;
}LinkStackNode, *LinkStack;

void InitStack(LinkStack *S){//初始化鏈棧 
    *S = (LinkStack)malloc(sizeof
(LinkStackNode)); (*S)->next = NULL; } int Push(LinkStack top, int x){// 進棧操作 LinkStackNode *temp; temp = (LinkStackNode*)malloc(sizeof(LinkStackNode)); if(temp == NULL) return 0; temp->data = x; temp->next = top->next; top->next = temp; return 1; } int
Pop(LinkStack top, int *x){//出棧操作 LinkStackNode *temp; temp = top->next; if(temp == NULL) return 0; *x = temp->data; top->next = temp->next; free(temp); return 1; } int GetNum(char ch){//返回字符對應的數字 return ch - 0; } bool IsEmpty(LinkStack top){//棧為空返回假 if(top->next == NULL) return false; return true; } int GetTop(LinkStack top){//返回棧頂元素 if(top->next == NULL) return 1; return top->next->data; } char Compare(char ch1, char ch2){//實現運算符優先級比較 switch(ch1){ case #: switch(ch2){ case #: return =; case +: case -: case *: case /: case ^: return <; } case +: switch(ch2){ case #: return >; case +: case -: return =; case *: case /: case ^: return <; } case -: switch(ch2){ case #: return >; case +: case -: return =; case *: case /: case ^: return <; } case *: switch(ch2){ case #: case +: case -: return >; case *: case /: return =; case ^: return <; } case /: switch(ch2){ case #: case +: case -: return >; case *: case /: return =; case ^: return <; } case ^: switch(ch2){ case #: case +: case -: case *: case /: return >; case ^: return =; } } } int Calculate(int a, char op, int b){//計算 a op b 的值 int c; switch(op){ case -: c = a - b; break; case +: c = a + b; break; case *: c = a * b; break; case /: c = a / b; break; case ^: c = pow(a, b); break; default : c = 0; } return c; } int ExpEvaluation(){//實現 LinkStack ovs, optr; InitStack(&ovs); InitStack(&optr); Push(optr, (int)#); printf("\n\nPlease input an expression(Ending with ‘#‘):\n"); char ch = getchar(); int num = 0, a, b, t, op, zan; while(ch != # || (char)GetTop(optr) != #){ while(ch >= 0 && ch <= 9){//如果數字不是一位數字,便把字符轉化為數字 num = num * 10 + GetNum(ch); ch = getchar(); } if(num != 0){//如果num不為0便進OVS棧 Push(ovs, num); num = 0;//把num置零 } else{ switch(Compare(ch, (char)GetTop(optr))){//對運算符優先級進行比較,實現對應三種關系的操作 case >: Push(optr, (int)ch); ch = getchar(); break; case =: case <: Pop(optr, &op); Pop(ovs, &a); Pop(ovs, &b); t = Calculate(a, (char)op, b); Push(ovs, t); break; } } } t = GetTop(ovs);//取棧頂元素,返回值 return t; } int main(){ int ans = ExpEvaluation(); printf("%d\n", ans); return 0; }

表達式求值(無括號)