資料結構-表示式樹
阿新 • • 發佈:2018-12-16
對於中綴表示式(e1)OP(e2),令根結點值為OP,左子樹為e1,右子樹e2,e1與e2遞迴。
如表示式:1+2*(3-4)-5/6 即 ((1) + ((2)*(3-4)))-((5)/(6))
可以形成如下的表示式樹。
先序:-+1*2-34/56 字首表示式
中序:1+2*3-4-5/6 中綴表示式
後序:1234-*+56/- 字尾表示式
其中字尾表示式可直接求值(不用考慮優先順序)。但求字尾式過程中需用優先順序,算符優先法實際在執行過程中隱含形成的邏輯結構就是一棵樹。
那麼給我們一個表示式,我們怎樣將其轉換為一個表示式樹呢?
輸入:一個表示式
輸出:各個結點的編號:左孩子編號、右孩子編號、該結點表示的字元。
首先是儲存結構定義:
//表示式樹
int lch[maxn], rch[maxn], nc; //每個結點的左右子結點編號 結點數
char op[maxn]; //結點的字元
演算法思想:
找到最後計算的運算子,是整顆表示式樹的根,然後遞迴。當p為0的時候考慮這個運算子,因為括號裡的運算子忽略,c1c2表示最優出現的加減號與乘除號, 如果括號外有加減號 ,肯定最後計算,如果沒有加減號,考慮乘除。如果全部沒有,說明整個表示式外面被一對括號括起來。去掉後遞迴呼叫最後運算的運算子s[c1] 它的左子樹是區間[x,c1] 右子樹是[c1+1,y]。
演算法實現:
int build_tree(char *s, int x, int y) { /*找到最後計算的運算子,是整棵表示式樹的根,然後遞迴 當p為0的時候考慮這個運算子,因為括號裡的運算子忽略。c1c2表示最優出現 的加減號與乘除號 如果括號外有加減號,肯定最後計算,如果沒有加減號, 考慮乘除如果全部沒有,說明整個表示式外面被一對括號括起來,去掉後遞迴 呼叫最後運算的運算子s[c1] 它的左子樹是區間[x,c1] 右子樹是[c1+1,y] */ int c1, c2, p, u, i; c1 = -1; c2 = -1; p = 0; if(y - x == 1) //僅一個字元 建立單獨結點 { u = ++nc; lch[u] = 0; rch[u] = 0; op[u] = s[x]; return u; } for(i = x; i < y; i++) switch(s[i]) { case '(': p++; break; case ')': p--; break; case '+': case '-': if(!p) c1 = i; break; case '*': case '/': if(!p) c2 = i; break; } if(c1 < 0) //找不到括號外的加減號,就用乘除號 c1 = c2; if(c1 < 0) return build_tree(s, x+1, y-1); //整個表示式被一對括號括起來 u = ++nc; lch[u] = build_tree(s, x, c1); rch[u] = build_tree(s, c1+1, y); op[u] = s[c1]; return u; }