原文,轉載如下:
用到了棧,並且遞歸實現了中序遍歷,后序遍歷,前序遍歷。
同時應該學會union的使用方法。
基礎知識:
一、表達式樹
表達式樹的樹葉是操作數(operand),加常數或變量名字,而其他的結點為操作數(operator)。由於這里所有的操作都是二元的,因此這棵特定的樹正好是二叉樹,雖然這是最簡單的情況,但是結點還是有可能含有多於兩個的兒子,這里我們不討論。
二、構造一棵表達式樹
之前我們實現過一個中綴表達式求值的具體程序,在求值過程中需要用兩個棧,並且代碼並不簡單。而這里你會看到,對於表達式樹的求值操作卻非常簡單,甚至只需要兩條語句。因為這里大部分操作都是遞歸定義,二遞歸函數本身都是很簡潔的,甚至比你想象的還要簡單,甚至只需要兩條語句。因為這里大部分操作都是遞歸定義,二遞歸函數本身都是很簡潔的,甚至比你想象的還要簡單!就像樹的遍歷操作。三種遍歷分別是先序遍歷、中序遍歷與后序遍歷,正好對應表達式的三種形式:前綴型、中綴型與后綴型。其中為大家熟知的是中綴形式,如2+3*(5-4)。前綴型表達式又叫波蘭式(Polish Notation),后綴性表達式又叫逆波蘭式(Reverse Polish Notation)。他們最早於1920年波蘭數學家Jan Lukasiewicz發明,這兩種表示方式的最大特點是不需要括號來表明優先級,他們經常用於計算機科學,特別是編譯器設計方面。
下面給出一種算法來把后綴表達式轉變成表達式樹。我們一次一個符號地讀入表達式。如果符號是操作數,那么就建立一個單結點樹並將它推入棧中。如果符號是操作符,那么就從棧中彈出兩棵樹T1和T2(T1先彈出)並形成一棵新的樹,該樹的根就是操作符,它的左、右兒子分別是T2和T1。然后將指向這顆樹的指針壓入棧中。
下面來看一個例子。設輸入為ab+cde+**
前兩個符號是操作數,因此創建兩棵單結點樹並將指向它們的指針壓入棧中。
接着,"+"被讀入,因此指向兩棵樹的指針被彈出,形成一棵新的樹,並將指向它的指針壓入棧中。
然后,c,d和e被讀入,在單個結點樹創建后,指向對應的樹的指針被壓入棧中。
接下來讀入"+"號,因此兩棵樹合並。
繼續進行,讀入"*"號,因此,彈出兩棵樹的指針合並形成一棵新的樹,"*"號是它的根。
最后,讀入一個符號,兩棵樹合並,而指向最后的樹的指針被留在棧中。
- #include <stdio.h>
- #include <stdlib.h>
- #define MAX 100
- /* 樹結點的設計 */
- typedef struct node
- {
- /* 數字和運算符 */
- union
- {
- char operator;
- int data;
- };
- struct node *lchild;
- struct node *rchild;
- }TreeNode;
- /* 樹棧 */
- typedef struct Tree_Stack
- {
- TreeNode *buf[MAX];
- int n;
- }TreeStack;
- /* 創建空棧 */
- TreeStack *create_empty_stack()
- {
- TreeStack *pstack;
- pstack = (TreeStack *)malloc(sizeof(TreeStack));
- pstack->n = -1;
- return pstack;
- }
- /* 入棧 */
- int push_stack(TreeStack *p, TreeNode *data)
- {
- p->n++;
- p->buf[p->n] = data;
- return 0;
- }
- /* 出棧 */
- TreeNode *pop_stack(TreeStack *p)
- {
- TreeNode *data;
- data = p->buf[p->n];
- p->n --;
- return data;
- }
- /* 判斷棧空 */
- int is_empty_stack(TreeStack *p)
- {
- if(p->n == -1)
- return 1;
- else
- return 0;
- }
- /* 創建后綴表達式樹 */
- TreeNode *create_express_tree(char *str, TreeStack *p)
- {
- int i = 0;
- TreeNode *current;
- TreeNode *left, *right;
- while(str[i])
- {
- if(str[i] >= '0' && str[i] <= '9')
- {
- current = (TreeNode *)malloc(sizeof(TreeNode));
- current->data = str[i] - '0';
- current->lchild = NULL;
- current->rchild = NULL;
- push_stack(p, current);
- }
- else
- {
- current = (TreeNode *)malloc(sizeof(TreeNode));
- current->operator = str[i];
- right = pop_stack(p);
- left = pop_stack(p);
- current->lchild = left;
- current->rchild = right;
- push_stack(p, current);
- }
- i++;
- }
- return p->buf[p->n];
- }
- /* 打印結點 */
- void print_node(TreeNode *p)
- {
- if(p->lchild == NULL && p->rchild == NULL)
- printf("%d ", p->data);
- else
- printf("%c ", p->operator);
- }
- /* 訪問結點 */
- int visit_node(TreeNode *p)
- {
- print_node(p);
- return 0;
- }
- /* 樹的后序遍歷 */
- void PostOrder(TreeNode *p)
- {
- if(p != NULL)
- {
- PostOrder(p->lchild);
- PostOrder(p->rchild);
- visit_node(p);
- }
- }
- /* 樹的中序遍歷 */
- void InOrder(TreeNode *p)
- {
- if(p != NULL)
- {
- InOrder(p->lchild);
- visit_node(p);
- InOrder(p->rchild);
- }
- }
- /* 樹的前序遍歷 */
- void PreOrder(TreeNode *p)
- {
- if(p != NULL)
- {
- visit_node(p);
- PreOrder(p->lchild);
- PreOrder(p->rchild);
- }
- }
- int main()
- {
- TreeNode *thead;
- TreeStack *pstack;
- int i = 0;
- char buf[100];
- scanf("%s", buf);
- pstack = create_empty_stack();
- thead = create_express_tree(buf, pstack);
- printf("PostOrder: ");
- PostOrder(thead);
- printf("\n");
- printf("InOrder: ");
- InOrder(thead);
- printf("\n");
- printf("PreOrder: ");
- PreOrder(thead);
- printf("\n");
- return 0;
- }
測試結果如下: