#include <iostream>
#include<cmath>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
using namespace std;
struct BiTNode //結點的數據
{
bool tag; //true爲數字,false爲字符
int num;
char c;
BiTNode *lchild,*rchild;
};
struct SqStack //順序棧
{
BiTNode *base; // 在棧構造之前和銷燬之後,base的值爲NULL
int stacksize; //當前已分配的存儲空間,以元素爲單位
int top1;
BiTNode **address; //存儲當前最頂端數據的地址,在構造二叉樹的時候會有地址的存儲返回子樹的根節點
int InitStack(int n) // 構造一個空棧S
{
base=new BiTNode[n];
stacksize=n;
address=new BiTNode *[n];
top1=0; //從0開始存數據
return OK;
}
int StackEmpty() // 若棧S爲空棧,則返回TRUE,否則返回FALSE
{
if(top1==0)
return TRUE;
else
return FALSE;
}
int Push(BiTNode *e) // 插入元素e爲新的棧頂元素
{
*(base+top1)=*e;
address[top1]=e;
top1++;
return OK;
}
BiTNode* Pop() // 若棧不空,則刪除S的棧頂元素,用e返回其值,並返回OK;否則返回ERROR/
{
if(top1<0) return ERROR;
top1--;
return address[top1];
}
};
BiTNode *tree; //定義樹
SqStack Stack; //定義棧,在建立二叉樹的的時候作爲中間變量,存儲部分子樹的根節點
void judge_value(BiTNode *t,char exprstring) //判斷字符string[i],加引用是爲了在調用函數的時候改變原來t的值
{
if(exprstring>='0'&&exprstring<='9') //爲常量
{
t->tag=true;
t->c='#'; //有數字的時候,字符賦值爲#
t->num=exprstring-48;
}
else //爲變量
{
t->tag=false;
t->num=-1; //當是字符形式,則數字賦值爲-1
t->c=exprstring;
}
}
int ReadExpr(char *exprstring,int len) //以字符序列的形式輸入語法正確的前綴表示式並構造表達式
{
int i; //len爲表達式的長度
BiTNode *p,*q;
tree=new BiTNode; //申請二叉樹的根結點的空間
tree->lchild=NULL;
tree->rchild=NULL;
if(len==1) //表達式長度爲1時,二叉樹只有根結點
judge_value(tree,exprstring[0]); //將exprstring[0]存入二叉樹的結點中
else
{
judge_value(tree,exprstring[0]); //同理
Stack.InitStack(len); //初始化棧
q=tree;
Stack.Push(tree); //入棧
Stack.Push(tree); //入棧,根結點入棧兩次是爲判斷先序輸入的表達式是不是正確的表達式
for(i=1;i<len&&!Stack.StackEmpty();i++)
{
p=new BiTNode;
judge_value(p,exprstring[i]); //將exprstring[i]存入二叉樹的結點中
p->lchild=NULL;
p->rchild=NULL;
if(exprstring[i]=='+'||exprstring[i]=='-'||exprstring[i]=='*'||exprstring[i]=='/'||exprstring[i]=='^')
{ //爲運算符,運算符入棧,左孩子不空,向左孩子走,否則,如果右孩子不空,向右孩子走
if(!q->lchild)
{
q->lchild=p;
Stack.Push(p);
q=p;
}
else
{
q->rchild=p;
Stack.Push(p);
q=p;
}
}
else //不是運算符,運算符出棧
{
if(!q->lchild)
{
q->lchild=p;
q=Stack.Pop();
}
else
{
q->rchild=p;
q=Stack.Pop();
}
}
}
if(Stack.StackEmpty()&&i>=len) return OK; //只有棧爲空的時候才把二叉樹構造成功
else
{
cout<<" 輸入的字符串無法構造成表達式!"<<endl;
return ERROR;
}
}
return OK;
}
int Compare(char c1,char c2) //比較兩個運算符的優先級,c1比c2優先,返回OK,否則返回ERROR
{
if((c1=='^'||c1=='*'||c1=='-'||c1=='+'||c1=='/')&&(c2=='^'||c2=='*'||c2=='-'||c2=='+'||c2=='/')) //c1和c2爲運算符
{
if(c1=='^') //c1爲指數運算符,則當c2不爲'^'時,c1比c2優先
{
if(c2!='^') return OK;
else return ERROR;
}
else if(c1=='*'||c1=='/') //c1爲乘法或除法運算符,則當c2爲'+'或'-',c1比c2優先
{
if(c2=='^'||c2=='*'||c2=='/') return ERROR;
else return OK;
}
else return ERROR; //其餘,c1不比c2優先
}
else return ERROR; //c1和c2不是運算符
}
void WriteExpr(BiTNode *Tree) //用帶括弧的中綴表示式輸出表達式
{
if(Tree) //樹不爲空
{ //先遞歸左子樹
if(Tree->lchild&&!Tree->lchild->tag) //二叉樹的左孩子不爲空,且左孩子爲字符
{
if(Compare(Tree->c,Tree->lchild->c)) //Tree->c的優先級大於Tree->lchild->c必須帶有並輸出()
{
cout<<"(";
WriteExpr(Tree->lchild);
cout<<")";
}
else //否則,不帶括弧輸出左子樹
WriteExpr(Tree->lchild);
}
else //否則,輸出左子樹
WriteExpr(Tree->lchild);
if(Tree->tag) //訪問輸出根結點的值
{
cout<<Tree->num;
}
else
cout<<Tree->c;
if(Tree->rchild&&!Tree->rchild->tag) //後遞歸右子樹,樹的右孩子不爲空,且右孩子爲字符
{
if(Compare(Tree->c,Tree->rchild->c)) //Tree->c比Tree->rchild->c優先
{
cout<<"(";
WriteExpr(Tree->rchild);
cout<<")";
} //帶括弧輸出右子樹
else
WriteExpr(Tree->rchild); //否則,不帶括弧輸出右子樹
}
else
WriteExpr(Tree->rchild);//否則,輸出右子樹
}
}
//賦值語句
void Assign(BiTNode *Tree,char V,int c,int *flag)
{
if(Tree)
{
if(Tree->tag==false&&Tree->c==V) //如果找到要賦值的變量,賦值
{
Tree->tag=true;
Tree->num=c;
*flag=1;
}
Assign(Tree->lchild,V,c,flag);//遞歸左子樹
Assign(Tree->rchild,V,c,flag);//遞歸左子樹
}
}
int Check(BiTNode *Tree) //檢查二叉樹中是否還存在沒有賦值的變量,以便求算數表達式的值
{
if(Tree&&Tree->tag==false) //二叉樹不爲空,並且根節點爲字符
{
if(Tree->c!='*'&&Tree->c!='^'&&Tree->c!='-'&&Tree->c!='+'&&Tree->c!='/')return ERROR; //是字符但不是運算符
if(Check(Tree->lchild)) //遞歸左子樹
Check(Tree->rchild); //遞歸右子樹
}
}
int Calculate(int n1,char opr,int n2) //運算符計算,返回計算結果值
{
int result;
switch(opr) //匹配多種情況
{
case '+':
result=n1+n2;
return result;
break;
case '-':
result=n1-n2;
return result;
break;
case '*':
result=n1*n2;
return result;
break;
case '/':
result=n1/n2;
return result;
break;
case '^':
result=pow(n1,n2);
return result;
break;
default:break;
}
}
int Value(BiTNode *Tree) //計算返回整個表達式的值
{
if(Tree) //二叉樹不爲空
{
if(!Tree->lchild&&!Tree->rchild&&Tree->tag) return (Tree->num); //結點的左孩子和右孩子爲空,爲葉子結點,返回結點的值
return Calculate(Value(Tree->lchild),Tree->c,Value(Tree->rchild)); //運算求值,後根遍歷的次序對表達式求值
}
}
void main()
{
char Expr_string[1000]; //存放剛開始輸入的字符串
int n,ttt=1;
while(ttt)
{
con: cout<<" 是否還要計算,是請按1,否請按0:";
cin>>ttt;
system("cls");
flushall(); //輸入之前清理緩衝區
cout<<" 請輸入前綴表達式:";
cin.getline(Expr_string,1000); //從鍵盤輸入一串字符串作爲表達式
n=strlen(Expr_string);
if(n==1) //輸入的表達式字符串長度爲1
{
if(Expr_string[0]=='+'||Expr_string[0]=='-'||Expr_string[0]=='*'||Expr_string[0]=='/'||Expr_string[0]=='^')//輸入的表達式只有一個運算符
{
cout<<" 表達式只有一個運算符,錯誤!"<<endl;
goto con;
}
else
if((Expr_string[0]>='0'&&Expr_string[0]<'9')||(Expr_string[0]>='a'&&Expr_string[0]<='z')||(Expr_string[0]>='A'&&Expr_string[0]<='Z'))
{
cout<<" 表達式只有一個字符"<<endl;
goto con;
}
else
{
cout<<" 輸入的字符不是運算符也不是變量或常量,錯誤!"<<endl;
goto con;
}
}
if(ReadExpr(Expr_string,n))
{
cout<<" 二叉樹構造成功!"<<endl;
cout<<" 中綴表達式爲:";
WriteExpr(tree);
cout<<endl;
int s=0,Assign_flag=0,t=Check(tree); //s記錄有幾個變量
while(!t) //檢驗表達式中是否有變量,如果有的話就重新賦予整數值,跳出循環式則整個表達式完整
{
if(t)cout<<" 表達式不存在未賦值的變量!"<<endl;
else
{
int c;char V;
cout<<" 表達式中存在變量未賦值!"<<endl;
cout<<" 請輸入要賦值的值:"; cin>>V;
cout<<" 請輸入要將賦值爲:"; cin>>c;
Assign(tree,V,c,&Assign_flag); //把所有的要賦予的值全在Assign賦值完成
if(Assign_flag)
{
cout<<" 賦值成功!"<<endl;
}
else
{
cout<<"表達式裏沒有"<<V<<",請重新輸入!"<<endl;
}
}
t=Check(tree);
}
cout<<" 整個表達式賦值成功!"<<endl;
cout<<" 表達式爲:";
WriteExpr(tree);
cout<<endl;
int result=Value(tree);
cout<<" 算數表達式的值爲: ";
WriteExpr(tree);
cout<<"="<<result<<endl;
}
else
goto con;
}
}
測試數據:
0
a
-91
+a*bc
+*5^x2*8x
+++*3^x3*2^x2x6
-^+5a32
--+++*3^x3*2^x2x6