表達式求值是高級語言編譯中的一個基本問題,是棧的典型應用實例。任何一個表達式都是由運算對象,運算符和界限符組成的。運算對象既可以是常數,也可以是被說明爲變量或常量的標識符;運算符可以分爲算術運算符,關係運算符和邏輯運算符三類;基本界限符有括號和表達式結束符等。
算法思想
1.規定運算符的優先級表。
2.設置兩個棧,)OVS(運算數棧),OPTR(運算符棧)。
3,自左向右掃描,進行如下處理。
若遇到運算數則進入OVS棧,若遇到運算符則與OPTR棧的棧頂運算符進行有限比較:
如果當前運算符優先級大於OPTR棧頂運算符優先級,則當前運算符進OPTR棧、
如果當前運算符優先級小於等於OPTR棧頂運算符優先級,則OPTR退棧一次,得到棧頂運算符&,連續退OVS棧兩次,得到運算數a 運算數b,對a b執行&運算,得到結果T,將T進OVS棧。
算法描述
#include<iostream>
using namespace std;
typedef char StackElementType;//棧數據類型
typedef struct StackNode{
StackElementType data; // 數據
StackNode *next; //指針
}LinkStackNode,*LinkStack;
//定義一個運算符數組集合
StackElementType opSet[]={"+-*/#"};
//初始化棧
void initStack(LinkStack &top){
LinkStack p;
p = (LinkStack)malloc(sizeof(LinkStackNode));//申請一個空間作爲頭結點
top = p; //頭指針指向頭結點
p->next = NULL; //空棧
}
//操作:進棧
bool push(LinkStack &top,StackElementType data){
LinkStack p;
p = (LinkStack)malloc(sizeof(LinkStackNode));//申請一個棧的空間
if(p == NULL)
return false; //申請空間失敗
//申請成功
p->data = data; //在申請的空間中放入一個數據
p->next = top;// 壓棧
top = p;//top指向棧頂
return true;
}
//出棧並返回出棧的值
bool pop(LinkStack &top,StackElementType &data){
LinkStack p;
p = top; //p爲棧頂
if(p->next== NULL) //棧爲空
return false;
//棧不爲空
top = p->next;//棧頂往下移一個
data = p->data;//p就爲棧頂 ,要出棧的數據
free(p);//釋放棧頂的空間
return true;
}
//判斷字符是不是運算符,是運算符返回1不是返回0
bool inOpSet(StackElementType a,StackElementType b[]){
int i = 0;
int flag = 0;
while(b[i]!='\0'){ //遍歷字符串
if(a == b[i])//有這個運算符
return 1;
i++;
}
return 0;//沒有找到這個運算符
}
//轉換 把字符型數據轉換成整形
void getNumber(StackElementType &a){
a = a - 48;//轉換
}
//獲取棧頂的元素,不改變原來棧的信息
StackElementType getTop(LinkStack top){
return top->data;//返回棧頂元素
}
//給運算符賦優先級
int judgePriority(StackElementType op){
int priority;//定義一個優先級
switch(op){
case '+':priority = 1;break;
case '-':priority = 1;break;
case '*':priority = 2;break;
case '/':priority = 2;break;
case '#':priority = 0;break;
}
return priority; //返回對應的優先級
}
//和棧頂的運算符進行比較,結果返回>或<或=
StackElementType compare(StackElementType a,StackElementType b){
int aa = judgePriority(a);//看a的優先級
int bb = judgePriority(b);//看b的優先級
if(aa > bb)
return '>';
else if(aa == bb)
return '=';
else
return '<';
}
//計算兩個數的運算
int execute(int a,StackElementType op,int b){
switch(op){//判斷是什麼運算
case '+':
return a+b;
break;
case '-':
return a-b;
break;
case '*':
return a*b;
break;
case '/':
return a/b;
break;
}
}
//無括號表達式運算
int expEvaluation(){
char ch;
StackElementType a,b,op,n,result;
LinkStack OPTR;//運算符棧
LinkStack OVS; //運算數棧
initStack(OPTR);//初始化棧
initStack(OVS);
push(OPTR,'#');//爲了便於操作,首先將#壓入OPTR棧
ch = getchar();//輸入一個字符
while(ch!='#'||getTop(OPTR)!='#'){//輸入的字符不爲#和棧頂的字符不爲#
if(!inOpSet(ch,opSet)){//opSet是運算符集合
getNumber(ch); //把字符數字變爲整形數字
push(OVS,ch);//把運算數壓入遠算數棧
ch = getchar();//再次輸入下一個字符
}
else
switch(compare(ch,getTop(OPTR))){//和棧頂的運算符進行比較優先級
case '>': //運算符優先級高
push(OPTR,ch); //壓棧
ch = getchar();//再次輸入字符
break;
case '=': //一樣優先級
case '<': //小於優先級
pop(OPTR,op);//出棧運算符
pop(OVS,b);//
pop(OVS,a);//出棧運算數
result = execute(a,op,b);//對ab進行運算
push(OVS,result);//把結果再次壓入棧中
break;
}
}
result = getTop(OVS);//獲取計算最後的結果
return result;//返回結果
}
//main函數,程序的入口地址
void main(){
int result=expEvaluation();
cout <<"計算最後的結果是:"<< result;
}