計算機無法識別數學表示式中的括號以及四則運算的先後順序,因此需要把數學表達示轉換成一種計算機能識別的,逆波蘭表示就能很好的解決這個問題。逆波蘭表示是數學表示式中的一種不需要括號的字尾表達法。即把乙個中綴數學表示式改變成乙個字尾表示。中綴表示的意思就是運算子在要計算的數字中間,而字尾表示就是運算子在要計算的數字之後。
例如:9+(3-1)*3+6/2 這就是乙個中綴表示,和正常的數學表示式一樣
931-3*+62/+ 這就是乙個字尾表示
轉換規則:
1.從左到右遍歷中綴表示式的每乙個數字和符號,若是數字就輸出,即成為字尾表示式的一部分;
2.若是符號,則判斷其與棧頂符號的優先順序,是右括號或優先順序不高於棧頂符號(乘除優先加減)則棧頂元素依次出棧並輸出,並將當前符號進棧,一直到最終輸出字尾表示式為止;若是左括號或者優先順序高於棧頂符號則入棧。
以上面的例子為例說明規則: (假定同一優先順序在棧內的優先順序高於棧外優先順序)
1.從左到右依次遍歷的第乙個字數是9,因為是數字,不入棧,照常輸出;
2.第二個字元是+,因為是符號,同時棧內為空,則入棧;
3.第三個字元是(,因為是左括號,入棧;
4.第四個字元是3,因為是數字,不入棧,照常輸出;
5.第五個字元是-,因為其優先順序比(低,入棧;
6.第六個字元是1,因為是數字,不入棧,照常輸出;
7.第七個字元是),因為是右括號,棧中靠近棧頂的第乙個左括號之後的所有元素輸出,該例中則把棧頂元素-輸出,同時棧中的左括號(出棧,但是並不輸出,右括號)也不輸出; //此時棧中就剩下字元+
8.第八個字元是*,因為其優先順序高於棧頂元素+,入棧;
9.第九個字元是3,因為是數字,不入棧,照常輸出;
10.第十個字元是+,因為其優先順序低於棧頂元素*,因此,棧頂元素*輸出,此時棧中的棧頂元素變為字元+,因為先進棧的優先順序高於後進棧(可理解為同一優先順序中棧內的優先順序高於棧外的優先順序),因此棧頂元素+輸出,此時,棧為空,字元+入棧;(當然,假如棧中還存在元素,但是其棧頂元素優先順序高於當前遍歷字元的優先順序,同樣把當前遍歷的字元入棧,如第5步;反之,繼續把棧中元素輸出,直到棧頂元素優先基高於當前遍歷的字元或者棧為空為止)
11.12.13各位看官根據我說的自己試著寫一下吧。最後結果就在上面哦。
上面所述是中綴轉字尾的具體實施步驟,根據這寫出**還是有一定難度的,當然大神除外,大神的話就不需要看下面了。
**的實現的難度在於怎麼去很好的區分四則運算符的優先順序,以及括號的優先順序,還有棧內棧外的優先順序。為解決這個麻煩事,作了以下假定:
棧內 數值 棧外 數值
- 4 - 3
+ 4 + 3
* 6 * 5
/ 6 / 5
( 2 ( 10
) 2
解釋下:加減的優先順序低於乘除的優先順序,且棧外的加減的優先順序低於棧內的優先順序,因此可以假設用數值3代表棧外的加減,棧內的加減的優先順序要比棧外高,因此只需要把數值加1即可,即4,同理可得乘除的,括號這比較特殊,左邊的括號在棧外時其優先順序要最大才行,因為遇到左括號就需要入棧,但是在棧中時為了能讓其他的再進來,就必須又要保證它的優先順序最小才行,右括號一遍歷到就需要把離棧頂最近的左括號上的所有元素都輸出,而且括號不要輸出,所以可以假定右括號在棧外的數值和棧中左括號值相等,當出現相等的情況時就能明白有一對括號出現。
說了一堆是不是沒看懂啊,沒關係,我現在就附上我寫的**,不過我這**有很大的侷限性,不過解決這個中綴轉字尾是沒什麼問題的。(侷限性就讓各位看官自己猜吧)
這是main.cpp檔案
#include"stack.h"
int main()
這是stack.h檔案
#pragma once
#include#include#include#include#define maxsize 30
#define elemtype char
typedef struct
sqstack;
void init_stack(sqstack *s); //初始化棧
bool my_push(sqstack *s, elemtype value); //入棧
bool my_pop(sqstack *s,elemtype *p); //出棧
bool mid_lat(sqstack *s, char *p); //中綴轉字尾
int sign_fig(char *p); //符號轉換成數值
這是stack.cpp檔案
#include"stack.h"
void init_stack(sqstack *s) //初始化棧
bool my_push(sqstack *s, elemtype value) //入棧
s->top++;
s->data[s->top] = value;
return true;
}bool my_pop(sqstack *s,elemtype *p) //出棧
*p = s->data[s->top];
s->top--;
return true;
}int sign_fig(char *p) //符號轉換成數值 }
bool mid_lat(sqstack *s, char *p)
else
else
else
//比較數值,確定優先順序
//棧內數值小於棧外數值時,即棧內棧頂元素的優先順序低於棧外優先順序
//則棧外元素進棧
if (num_in < num_out)
//棧內數值大於棧外數值時,則出棧,輸出
else if (num_in > num_out)
//相等時,代表出現了一對括號,棧中左括號出棧,但是不輸出
else
}} }
while (s->top != -1) //遍歷完後,清空棧內元素,把還存在棧中的符號輸出
*q = '\0'; //因為是用字串來表示表示式,最後需要新增『\0』
return true;
}
中綴轉字尾 逆波蘭
具體步驟如下 遇到括號時 重複步驟2至5,直到表示式的最右邊 將s1中剩餘的運算子依次彈出並壓入s2 依次彈出s2中的元素並輸出,結果的逆序即為中綴表示式對應的字尾表示式 例如 中綴表示式 1 2 3 4 5 轉成字尾表示式 123 4x 5 實現 只考慮正整數 public class polan...
逆波蘭計算 中綴轉字尾 字尾表示式計算
我們利用棧將中綴表示式轉換為字尾表示式 逆波蘭表示式 來計算表示式 此程式支援整數運算 遍歷中綴表示式,遇到運算元就輸出,遇到符號就壓入棧中 棧中的運算子為掛起狀態 但是操作符的壓棧出棧有如下規則 碰到運算元壓入棧中,碰到運算子提取棧頂兩個元素進行相應的操作,將運算元壓入棧中,直到整個表示式遍歷完成...
逆波蘭中綴轉字尾表示式並求值
建立鏈棧 linkstack.h pragma once typedef int elemtype typedef struct node node typedef struct linkstack linkstack,ptrstack 初始化 void init ptrstack stack 入棧...