逆波兰表达式[栈 C 语言 实现]
逆波蘭表達式
逆波蘭表達式又叫做后綴表達式。在通常的表達式中,二元運算符總是置于與之相關的兩個運算對象之間,這種表示法也稱為中綴表示。波蘭邏輯學家J.Lukasiewicz于1929年提出了另一種表示表達式的方法,按此方法,每一運算符都置于其運算對象之后,故稱為后綴表示。
?
a+b ---> a,b,+
a+(b-c) ---> a,b,c,-,+
a+(b-c)*d ---> a,b,c,-,d,*,+
a+d*(b-c)--->a,d,b,c,-,*,+
1、將一個中序表達式轉化成為逆波蘭表達式
?
構造兩個棧S1,S2,S1用來存放表達式,S2用來暫時存放運算符,最后完成后,該棧是清空的。
(1)如果遇到的是數字,直接進棧S1
(2)如果遇到的是左括號,進棧S2
(3)如果遇到的是右括號,將S2中的運算符全部出棧壓入S1中,注意括號不壓入
(4)如果遇到的運算符
?
? ? ? ? ?1.如果此時棧S2為空,則直接將運算符加入到棧S2中;
? ? ? ? ?2.如果此時棧S2不為空,當前運算符的優先級大于等于棧頂運算符的優先級,那么直接入棧S2;
? ? ? ? ?3.如果此時棧S2不為空,當前運算符的優先級小于棧頂運算符的優先級,則將棧頂運算符一直出棧壓入到棧S1中, ?直到棧為空或者遇到一個運算符的優先級小于等于當前遍歷的運算符的優先級,然后將該運算符壓入到棧S2中。 ? ?
(5)遍歷完整個中序表達式之后,如果棧S2中仍然存在運算符,那么將這些運算符依次出棧壓入到棧S1中,直到棧為空。
2、利用逆波蘭表達式求值
?
維護一個結果棧S3,該棧最后存放的是表達式的值。從左至右的遍歷棧S1
(1)如果遇到的是數字,直接將數字壓入到S3中
(2)如果遇到的是單目運算符,取S3棧頂的一個元素進行運算之后,將結果壓入到棧S3中
(3)如果遇到的是雙目運算符,取S3棧頂的兩個元素,首先出棧的在左,后出棧的在右進行雙目運算符的計算,將結果壓入到S3中
遍歷完整個棧S1,最后S3中的值就是逆波蘭表達式的值。
?
棧實現表達式計算【數據結構】
思路:
所包含的運算符有‘+’,‘-’,‘*’,‘/’,‘(’,‘)’。
(1)建立兩個棧,一個用來存儲操作數,另一個用來存儲運算符, 開始時在運算符棧中先壓入‘/0’,一個表達式的結束符。
(2)然后從左至右依次讀取表達式中的各個符號(操作數或者運算符);
(3)如果讀到的是操作數直接存入操作數棧;
(4)如果讀到的是運算符,則作進一步判斷:
若讀到的是‘/0’結束符,而且此時運算符棧的棧頂元素也是‘/0’結束符,則運算結束,輸出操作數棧中的元素即為最后結果。
若讀到的是‘(’或者讀到的運算符的優先級比目前的運算符棧中的棧頂元素的優先級高,則將運算符直接存入運算符棧,繼續讀表達式中的下一個符號,重復步驟(3)和(4);
若讀到的是‘)’,而且此時運算符棧的棧頂元素是‘(’結束符,則將運算符棧中的棧頂元素退出來,繼續讀表達式中的下一個符號,重復步驟(3)和(4);
若讀到的運算符的優先級等于或小于之前的運算符的優先級,則從操作數中退出2個,從運算符中退出一個進行運算,將運算結果存入操作數棧;再把之前讀到的運算符與目前的運算符棧頂比較,重復步驟(4)(即現在不讀下一個元素);
?
/* 輸入: 9+(3-1)*3+10/2 輸出 20注意:其實注釋的地方可以用來調試,本人主要根據大話數據結構的思路寫出來的如果有什么地方錯了,多謝提出。 */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> using namespace std; struct stack{char data[101];int top; };struct stack2{int data1[101];int top; }; struct stack tak; struct stack2 tak2;bool jia(char s){if(s=='+' || s=='-')return true;else return false; } bool ch(char s){if(s=='*' || s=='/')return true;else return false; } int number(int y, int x, char s){if(s=='+')return x + y;if(s=='-')return x - y;if(s=='*')return x * y;if(s=='/' )return x / y; }int main(){char s1[20];scanf("%s",&s1);getchar();tak.top = 0;tak2.top = 0;//中綴表達式轉化為后綴表達式 for(int i=0;i<strlen(s1);i++){if(s1[i]>='0' && s1[i]<='9'){int tep = s1[i]-'0';while(s1[i+1]>='0' && s1[i+1]<='9'){tep *= 10;i++;tep += s1[i]-'0'; } // printf("%d ",tep);tak2.top++;tak2.data1[tak2.top] = tep;}else{if(tak.top==0 || tak.data[tak.top]=='('){tak.top++;tak.data[tak.top] = s1[i];}else{char temp = tak.data[tak.top];if( jia(temp) && (ch(s1[i]) || jia(s1[i]) || s1[i]=='(') ){tak.top++;tak.data[tak.top] = s1[i]; }else if(ch(temp) && (ch(s1[i]) || s1[i]=='(')){tak.top++;tak.data[tak.top] = s1[i];}else if(s1[i]==')'){while(tak.top>0){if(tak.data[tak.top]=='('){tak.top--;break;} // printf("%c ",tak.data[tak.top]);int t1 = tak2.data1[tak2.top];tak2.top--;int t2 = tak2.data1[tak2.top];int t3 = number(t1,t2,tak.data[tak.top]);tak2.data1[tak2.top] = t3;tak.top--;}}else if(ch(temp) && jia(s1[i])){while(tak.top>0){if(tak.data[tak.top]=='('){break;} // printf("%c ",tak.data[tak.top]);int t1 = tak2.data1[tak2.top];tak2.top--;int t2 = tak2.data1[tak2.top];int t3 = number(t1,t2,tak.data[tak.top]);tak2.data1[tak2.top] = t3;tak.top--;}tak.top++;tak.data[tak.top] = s1[i];}} } }while(tak.top>0){ // printf("%c ",tk.data[tak.top]);int t1 = tak2.data1[tak2.top];tak2.top--;int t2 = tak2.data1[tak2.top];int t3 = number(t1,t2,tak.data[tak.top]);tak2.data1[tak2.top] = t3; // cout<<" t3 = "<<t3<<endl;tak.top--;}printf("%d",tak2.data1[tak2.top]);return 0; }?
轉載于:https://www.cnblogs.com/0526yao/p/10372092.html
總結
以上是生活随笔為你收集整理的逆波兰表达式[栈 C 语言 实现]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: visio2016 两线相交去圆弧
- 下一篇: Mybatis一级缓存和二级缓存 Red