1+2*2+(3/(5+4))
人類習慣看此種表示方法 中序(infix)
要處括弧 (parenthesis) 和 operator 的優先權 (precedence) 實在是很麻煩
所以才要有此 postfix 這種表示方法,
它為電腦去除了 優先權, 及括弧的問題
因此, 電腦在計算一個expression時
方法是這樣:
所有的 infix 先轉成 postfix
1 2 2 * 3 5 4 + / + +
並且把資料存起來
接者把postfix的東西push到 stack裡
如果是數字 直接push
如果是運算子 從stack pop出兩個數字, 運算完再push回去
至於要中序怎麼轉後序呢
如果是運算元 (operand), 存進postfix_array
如果是個運算子 (operator), 將它先push到 op_stack
遇到下個運算子時, 將op_stack裡優先權比它大的全部pop出來存到postfix_array裡
為了解決括弧的優先問題
優先權設為兩種
一種是在stack裡的
另一種是coming的
左括弧 為coming時, 其優先權最大, 因此在op_stack裡的運算子沒有一個能pop出來
左括弧在op_stack時, 其優先權最小, 因此它不會因為coming的運算子比他小, 而被pop出來
code
typedef enum {end,add,sub,mul,div,mod,lp,rp,not} Operator; struct stack{ Operator op[OP_MAX]; long data[OP_MAX]; }; double eval_postfix(struct stack *post) { int i = 0, top = -1; double eval[OP_MAX]; Operator op; while(post->op[i]!=end){ if(post->op[i]!=not){ op = post->op[i]; if(op==add) eval[top-1] = eval[top-1]+eval[top]; if(op==sub) eval[top-1] = eval[top-1]-eval[top]; if(op==mul) eval[top-1] = eval[top-1]*eval[top]; if(op==div) eval[top-1] = eval[top-1]/eval[top]; top--; } else eval[++(top)] = post->data[i]; i++; } return eval[top]; } void in_to_post(const char *expr,struct stack *s) { Operator op,ops[OP_MAX]; int i = 0, optop = 0, stop = -1,isf = 0; double t = 0,frac = 0; int icp[ ] = {0,2,2,3,3,3,9}, isp[ ] = {0,2,2,3,3,3,1}; ops[optop] = end; while(expr[i]){ if(expr[i]>='0'&&expr[i]<='9'){ t = expr[i++]-'0'; while(expr[i]>='0'&&expr[i]<='9'){ t *= 10.0; t += expr[i++]-'0'; } if(expr[i]=='.'){ i++; while(expr[i]>='0'&&expr[i]<='9'){ frac /= 10.0; frac += expr[i++]-'0'; } } s->data[++stop] = t+frac; s->op[stop] = not; } if(!expr[i]) break; switch(expr[i]){ case '+': op = add;break; case '-': op = sub;break; case '*': op = mul;break; case '/': op = div;break; case '%': op = mod;break; case '(': op = lp;break; case ')': op = rp;break; } if(op==rp){ while(ops[optop]!=lp) s->op[++stop] = ops[optop--]; optop--;//remove left parenthesis } else{ while(isp[ops[optop]]>=icp[op]) //have '=': a+b+c => ab+c+, don't have => abc++ s->op[++stop] = ops[optop--]; ops[++optop] = op; } i++; } while(ops[optop]!=end) s->op[++stop] = ops[optop--]; s->op[++stop] = end; }
Wow
回覆刪除