在學習《資料結構與演算法分析》時,第3章有乙個練習題,第1問要求編寫程式將中綴表示式轉換成字尾表示式,這個還是容易的,因為書上已經給了詳細的思路,用棧就可以了,實現方法在我另一篇部落格裡有寫到-中綴表示式轉字尾表示式。這題最後一問是讓把字尾表示式轉換成中綴表示式,這個還是有點難度的,當時是想按計算字尾表示式的方法得到中綴表示式,思路很簡單,也很好實現,但這樣會出現乙個問題——轉換結果裡有多餘的括號,比如會產生((a+b)+(c+d))這樣的結果,或者(a+(b*(c*d)))這樣的結果,計算結果裡的很多括號都是多餘的,看著很不舒服,但也沒想到好的解決辦法,所以當時就暫時把這個問題擱置了。
在看到第4章,二叉樹那一節時,書上介紹了一種將字尾表示式轉換成二叉樹的方法:即一次乙個符號地讀入表示式,如果符號是運算元,那麼就建立乙個單節點樹並將乙個指向它的指標推入棧中。如果符號是操作符,那麼就從棧中彈出指向兩棵樹t1和t2的那兩個指標(t1的先彈出)並形成一顆新的樹,該樹的根就是操作符,它的左右兒子分別指向t1和t2。然後將指向這顆樹的指標壓入棧中。書上有具體的例子,我就不再贅述。轉換完成後,我們只要中序遍歷該樹,並加上相應的括號,就完成了字尾表示式到中綴表示式的轉換。
樹的結構和棧的結構:
struct treenode
;struct structnode
;
字尾表示式轉換為樹:
tree postfixtotree(char *str)
/*如果符號是運算子*/
else
}t = topandpop(s);
return t;
}
下面的任務就是把樹轉換成中綴表示式了。前面已經說過,中序遍歷樹即可得到中綴表示式,但得到的是錯誤的、不帶括號的表示式,那麼如何在表示式中加入括號呢?
這個問題我一開始是想從中序遍歷樹的程式入手,下面是我找到的兩個程式,乙個是遞迴中序遍歷,乙個是非遞迴中序遍歷。
/*中序遍歷二叉樹-遞迴*/
void inorder_r(tree t)
}/*中序遍歷二叉樹-非遞迴*/
void inorder_nr(tree t)
//如果tmptree的左孩子為空,則輸出tmptree節點,並將其右孩子設為當前節點,看起是否為空
else}}}
顯然,遞迴的程式非常簡單,簡單到無法插入括號。。。
非遞迴的程式相對複雜,具體原理這裡不多說,但要適當的插入括號的話,也是無法下手。。。
最後我乾脆把這兩個都刪了,重新想了乙個辦法,總體思路使用遞迴實現括號的新增,具體如下:
這是中綴表示式 a+b*c+(d*e+f)*g 的二叉樹形式。
以上圖為例,採用遞迴的思想,假設我們已經寫出了乙個將二叉樹轉換成中綴表示式的程式:
1.對於根節點「+」,我們可以先計算出其左邊分支的中綴表示式和右邊分支的中綴表示式;
2.然後把左右兩部分以「+」號連線起來即可;
3.依次遞推,就可得到整個樹的中綴表示式。
4.括號的新增方法:
(1)對於當前節點,如果其左節點是操作符,且運算優先順序小於當前節點操作符,則給左子樹的中綴表示式加括號;
(2)對於當前節點,如果其右節點是操作符,且運算優先順序不大於當前節點操作符,則給右子樹的中綴表示式加括號。
程式如下:
/*樹轉換為中綴表示式*/
char *treetoinfix(tree t)
if (t->right)
//把左右兩部分和當前節點連線起來
*tep = t->element;
strcat(str, strl);
strcat(str, tep);
strcat(str, strr);
} //返回以當前節點作為根節點的樹轉換成的中綴表示式
return str;
}
不得不說,遞迴真的是賞心悅目啊!
下面是主程式中用到的幾個子程式:
/*判斷是否為運算子*/
int issymbol(char c)
/*計算優先順序*/
int priority(char c)
}/*比較優先順序*/
int comparepri(char x, char y)
/*給字串加括號*/
char *brackets(char *str)
至此,所有的問題都解決了,來一波測試:
int main(void)
}
測試結果:
結果很完美啊有木有!
可能有的童鞋注意到了測試結果裡面的第二個例子好像多了個括號,其實沒錯,那是為了保證運算次序的。因為如果不加括號就是(a+b)先乘c再乘(d+e)了,但從字尾表示式我們也能看出來,真實的運算次序是c先乘(d+e),然後再和(a+b)相乘。
中綴表示式轉字尾表示式
using system using system.collections.generic using system.text namespace 中綴表示式轉字尾表示式 class convert public void run top break case case while top 1 st...
中綴表示式轉字尾表示式
將乙個普通的中綴表示式轉換為字尾表示式的一般演算法是 首先需要分配2個棧,乙個作為臨時儲存運算子的棧s1 含乙個結束符號 乙個作為輸入字尾表示式的棧s2 空棧 s1棧可先放入優先順序最低的運算子 注意,中綴式應以此最低優先順序的運算子結束。可指定其他字元,不一定非 不可。從中綴式的左端開始取字元,逐...
中綴表示式轉字尾表示式
演算法 1.設定乙個運算子棧 初始時可以將棧頂運算子置為 2.按順序掃瞄中綴表示式,當輸入為運算元時就將其輸出到字尾表示式中 3.當輸入為運算子時,則比較輸入運算子和棧頂運算子的優先順序。若輸入運算子的優先順序高於棧頂運算子的優先順序,則將輸入運算子入棧 否則,棧頂運算子的優先順序高於或等於輸入運算...