利用棧實現加減乘除冪功能
阿新 • • 發佈:2019-01-02
如何用棧來實現加減乘除冪的運算呢?應考慮下面幾點。
1.分別用一個棧x存符號,另一個棧y存數值。
2.遇到數字就壓棧,遇到符號ch要比較棧頂的符號與當前的符號ch,編寫一個判別函式prev,若能進行運算,則返回真,不能返回假.以下是判別函式的幾種情況:
(1)如果棧頂符號為* ^ / 則不用考慮輸入拿來比較的符號,直接返回真。
(2)如果棧頂符號和拿來比較的符號ch為+或者-,也返回真.
(3)其他遇到棧頂元素為括號或者棧頂符號為+or-,而ch為* / ^等等情況,直接返回假。
程式碼如下:
bool prev(char s1,char s2 ){ //判斷符號s1 與 s2 的優先級別的函式 if(s1=='^'||s1=='*'||s1=='/') //如果棧頂符號為* ^ / 則不用考慮輸入拿來比較的符號,直接返回真 return true; else if((s1=='+'||s1=='-')&&(s2=='+'||s2=='-')) //如果棧頂符號和拿來比較的符號為+或者-,也返回真 return true; else return false; //其他情況都返回假 }
3.編寫計算函式result,並將計算結果壓入棧中,注意計算的是當前輸入符號ch前面的符號,計算完後要將當前符號ch壓入符號棧內。
void result(char ch,SeqStack<T> &s) //計算並將計算結果壓入棧中 { T x,y,result; x=s.Pop(); y=s.Pop(); switch(ch) { case '+':result=y+x;break; case '-':result=y-x;break; case '*':result=y*x;break; case '/':result=y/x;break; case '^':result=pow(y,x);break; } s.Push(result); return ; }
具體程式碼如下:
#include <iostream> #include <cstring> #include <cmath> #include <cstdio> #include <cstdlib> #include <assert.h> #define Max 100 using namespace std; bool prev(char s1,char s2 ){ //判斷符號s1 與 s2 的優先級別的函式 if(s1=='^'||s1=='*'||s1=='/') //如果棧頂符號為* ^ / 則不用考慮輸入拿來比較的符號,直接返回真 return true; else if((s1=='+'||s1=='-')&&(s2=='+'||s2=='-'))//如果棧頂符號和拿來比較的符號為+或者-,也返回真 return true; else return false; //其他情況都返回假 } template <class T> class SeqStack { public: SeqStack():top(-1){} ~SeqStack(){top=-1;} T Pop(); T getTop(); void Push(T x); bool IsEmpty(); bool IsFull(); private: T A[Max]; int top; }; template <class T> void result(char ch,SeqStack<T> &s) //計算並將計算結果壓入棧中 { T x,y,result; x=s.Pop(); y=s.Pop(); switch(ch) { case '+':result=y+x;break; case '-':result=y-x;break; case '*':result=y*x;break; case '/':result=y/x;break; case '^':result=pow(y,x);break; } s.Push(result); return ; } int main() { SeqStack<char> x; //符號棧 SeqStack<double> y; //數值棧 char ch,c; double operand; x.Push('0'); while(1) { cin.get(ch); if(ch=='+'||ch=='-'||ch=='*'||ch=='/') //若是+-*/則要與符號棧棧頂元素比較,決定是否運算 { c=x.getTop(); //c儲存當前棧頂值 while(prev(c,ch)) //符號比較返回真,則要計算,迴圈直到棧內能計算的符號全部計算 { result(c,y); //注意計算時使用的是符號棧中棧頂符號 x.Pop(); //彈出剛剛計算過的符號c c=x.getTop(); //c儲存當前符號棧棧頂的元素進行迴圈 } x.Push(ch); //計算結束壓入剛剛輸入的符號 } else if(ch=='^'||ch=='(') //遇到符號^或者(直接壓棧,不用考慮比較符號和計算 x.Push(ch); else if(ch==')') //遇到右括號,要對棧中元素進行迴圈計算,直到遇到左括號( { c=x.getTop(); while(c!='(') //此時的迴圈條件不是判斷符號,遇到符號就要計算,因為括號裡前面的元素,已經按優先順序計算好 { result(c,y); x.Pop(); c=x.getTop(); } x.Pop(); //彈出(符號 } else if(isdigit(ch)) //是數字,放回輸入流,重新輸入數字,壓棧 { cin.putback(ch); cin>>operand; y.Push(operand); } else if(ch=='\n') //遇到回車符,計算棧中仍未計算的數字,跳出迴圈 { c=x.getTop(); while(c!='0') { result(c,y); x.Pop(); c=x.getTop(); } cout<<y.Pop()<<endl;break; } } return 0; } template <class T> T SeqStack<T>::Pop() { assert(top!=-1); T x; x=A[top]; top--; return x; } template <class T> void SeqStack<T>::Push(T x) { assert(top!=Max-1); top++; A[top]=x; return ; } template <class T> T SeqStack<T>::getTop() { assert(top!=-1); return A[top]; } template <class T> bool SeqStack<T>::IsEmpty() { if(top==-1) return true; else return false ; } template <class T> bool SeqStack<T>::IsFull() { if(top==Max-1)return true; else return false; }