1. 程式人生 > >表達式樹計算多項式

表達式樹計算多項式

tle data cli 一段 copy 結束 node repr ces

計算多項式一種方法是轉化為逆波蘭式後進行計算。

還有就是可以使用表達式樹。

具體原理:

因為 + - * / 運算符是雙目運算符,可以將一個表達式放到一顆二叉樹上,左右分支為操作數,非葉子節點存放操作符,葉子節點存放數字,每棵子樹對應表達式的一部分,每棵子樹的根存放當前式子中最後運算的運算符。

如何找到最後運算的運算符:

如果整個表達式包含在括號裏就去除外層括號

如果最外層沒有括號且表達式的一部分包含在括號裏,則括號中的運算符一定不是最後運算的

先乘除後加減

自左向右結合,同優先級取最右面的操作符

在找到一段表達式中最後運算的運算符後遞歸的對這個運算符的左段和右段的表達式按照相同的原理遞歸的繼續展開

代碼部分:

下面的代碼只能計算0-10內整數的加減乘除

[cpp] view plain copy
  1. #include<iostream>
  2. #include<cstring>
  3. using namespace std;
  4. struct node{
  5. char op;
  6. node *left,*right,*parent;
  7. node(char x):op(x),left(NULL),right(NULL),parent(NULL){}
  8. }*root;
  9. node* build(char *E,int left,int right){//E是表達式 left和right分別是需要展開的式子在整個表達式中的左右邊界
  10. node*pointer=new node(E[left]);
  11. if(left==right) //式子只有一個數字時就結束遞歸
  12. return pointer;
  13. int a=-1,b=-1,n=0;
  14. for(int i=left;i<=right;i++){
  15. switch(E[i]){
  16. case ‘(‘:n++;break;
  17. case ‘)‘:n--;break;
  18. case ‘+‘:case ‘-‘:if(n==0)a=i;break;
  19. case ‘*‘:case ‘/‘:if(n==0)b=i;
  20. }
  21. }
  22. if(a<0)a=b;//先乘除後加減
  23. if(a<0)return build(E,left+1,right-1);//外圍有大括號包圍的情況
  24. else{
  25. pointer->op=E[a];
  26. pointer->left=build(E,left,a-1);
  27. pointer->right=build(E,a+1,right);
  28. }
  29. return pointer;
  30. }
  31. double calculate(node* root){//根據表達式樹求值
  32. if(root->op>=‘0‘&&root->op<=‘9‘)return root->op-‘0‘;
  33. else{
  34. double ans;
  35. switch(root->op){
  36. case ‘+‘:ans=calculate(root->left)+calculate(root->right);break;
  37. case ‘-‘:ans=calculate(root->left)-calculate(root->right);break;
  38. case ‘*‘:ans=calculate(root->left)*calculate(root->right);break;
  39. case ‘/‘:ans=calculate(root->left)/calculate(root->right);break;
  40. }
  41. return ans;
  42. }
  43. }
  44. int main(){
  45. char p[1000];
  46. while(cin>>p){
  47. root=build(p,0,strlen(p)-1);
  48. cout<<calculate(root)<<endl;
  49. memset(p,0,sizeof(p));
  50. }
  51. }

表達式樹計算多項式