什麼是波蘭表達式
人類最熟悉的一種表達式1+2,(1+2)*3,3+4 *2+4等等都是中綴表示法。對於人們來說,也是最直觀的一種求值方式,先算括號裏的,
然後算乘除,最後算加減,但是,計算機處理中綴表達式卻並不方便,因爲沒有一種簡單的數據結構可以方便從一個表達式中間抽出
一部分算完結果,再放進去,然後繼續後面的計算(鏈表也許可以,但是,代價也是不菲)。
因此,1920年,波蘭科學家揚·武卡謝維奇(Jan ukasiewicz)發明了一種不需要括號的計算表達式的表示法將操作符號寫在操作數之前,也就是前綴表達式,即波蘭式(Polish Notation, PN)。
中綴表達式轉逆波蘭表達式
這裏使用栗子:(1 + 2 * (4 - 3) + 6/2)
算法僞代碼(如果不清楚流程的話,務必要先看一下)
輸入:中綴表達式串
輸出:後綴表達式串
PROCESS BEGIN:
1.從左往右掃描中綴表達式串s,對於每一個操作數或操作符,執行以下操作;
2.IF (掃描到的s[i]是操作數DATA)
將s[i]添加到輸出隊列中;
3.IF (掃描到的s[i]是開括號'(')
將s[i]壓棧;
4.WHILE (掃描到的s[i]是操作符OP)
IF (棧爲空 或 棧頂爲'(' 或 掃描到的操作符優先級比棧頂操作符高)
將s[i]壓棧;
BREAK;
ELSE
出棧至輸出隊列中
5.IF (掃描到的s[i]是閉括號')')
棧中運算符逐個出棧並輸出,直到遇到開括號'(';
開括號'('出棧並丟棄;
6.返回第1.步
7.WHILE (掃描結束而棧中還有操作符)
操作符出棧並加到輸出隊列中
PROCESS END
所以將上面的栗子放進去走一圈出來會怎樣?
in>>(1 + 2 * (4 - 3) + 6/2)
out<<1 2 4 3 -*+ 6 2 / +
瞭解流程之後,我們來看個表:對於上面的栗子的轉換
後綴表達式運算流程
逆波蘭表達式的計算就比較簡單了。以上面結果中的隊列爲輸入,同時再準備一個棧用於運算。具體流程如下:
- 將隊列中的數據依次出隊,然後壓棧;
- 在出隊的過程中如果遇到運算符,則從棧中彈出2個運算數,分別作爲右運算數和左運算數,進行運算;
- 將步驟2的運算結果入棧;
- 跳入步驟1,繼續進行出隊操作。
對上面栗子進行流程化:
①
②
③
放碼過去
這是一個多項式計算器的代碼,註釋我就沒放。
#ifndef _STACK_H_
#define _STACK_H_
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
typedef struct node
{
int data;
struct node *next;
}Node;
typedef struct stack
{
Node *top;
}Stack;
void Init(Stack *s);
int Empty(Stack *s);
void Push(Stack *s, int data);
void Pop(Stack *s);
int GetTop(Stack *s);
#endif
#include "stack.h"
void Init(Stack *s)
{
if (NULL == s)
return;
s->top = NULL;
}
int Empty(Stack *s)
{
if (NULL == s)
return 0;
if (NULL == s->top)
return 1;
return 0;
}
void Push(Stack *s,int data)
{
if (NULL == s)
return;
Node *node = (Node *)malloc(sizeof(Node)/sizeof(char));
if (NULL == node)
return;
node->data = data;
node->next = s->top;
s->top = node;
}
void Pop(Stack *s)
{
if (NULL == s)
return;
if (Empty(s) == 1)
return;
Node *tmp = s->top;
s->top = tmp->next;
free(tmp);
}
int GetTop(Stack *s)
{
if (NULL == s)
return;
if (Empty(s) == 1)
{
printf ("無棧頂元素\n");
exit(-1);
}
return s->top->data;
}
#include <stdio.h>
#include "stack.h"
#include <string.h>
int Ope_judge(Stack *s_ope,int ope)
{
if(Empty(s_ope))
return 1;
int top = GetTop(s_ope);
switch(top)
{
case '+':
case '-':
if(ope == '*' || ope == '/' || ope == '(')
return 1;
break;
case '*':
case '/':
if( ope == '(')
return 1;
break;
case '(':
if(ope == ')')
{
Pop(s_ope);
}
return 1;
default :
break;
}
return 0;
}
void Calc(Stack *s_ope,Stack *s_num)
{
int num1 = GetTop(s_num);
Pop(s_num);
int num2 = GetTop(s_num);
Pop(s_num);
int ope = GetTop(s_ope);
Pop(s_ope);
int res;
switch(ope)
{
case '+':
res = num2 + num1;
break;
case '-':
res = num2 - num1;
break;
case '*':
res = num2 * num1;
break;
case '/':
res = num2 / num1;
break;
default:
break;
}
Push(s_num,res);
}
void Ope_deal(Stack *s_ope,Stack *s_num,int ope)
{
if(Ope_judge(s_ope,ope) == 1)
{
Push(s_ope,ope);
}
else
{
while(Ope_judge(s_ope,ope) == 0)
{
Calc(s_ope,s_num);
}
if(ope != ')')
Push(s_ope,ope);
}
}
int main()
{
char buf[100];
fgets(buf,100,stdin);
buf[strlen(buf)-1] = '\0';
Stack s_num;
Stack s_ope;
Init (&s_num);
Init (&s_ope);
char *p = buf;
while(*p)
{
if(*p >= '0' && *p <= '9')
{
int num = 0;
while(*p >= '0' && *p <= '9')
{
num = num *10 + *p - '0';
p++;
}
Push(&s_num , num);
continue;
}
Ope_deal(&s_ope,&s_num,*p);
p++;
}
while(!Empty(&s_ope))
{
Calc(&s_ope,&s_num);
}
int res = GetTop(&s_num);
printf ("計算結果爲:%d\n", res);
return 0;
}
喜歡的話可以點贊關注哦。