在前面先后介紹了二叉樹先序遍歷的非遞歸算法和中序遍歷的非遞歸算法,這里則來介紹二叉樹后序遍歷非遞歸算法,二叉樹后序非遞歸遍歷真的非常之
重要,因為它具有獨特的特性(文章結尾會闡述),所以,在很多與二叉樹相關的復雜算法中,經常要用到二叉樹后序遍歷的非遞歸算法。並且在互聯網面試筆
試也經常考察該算法,所以,我們應該對二叉樹后序遍歷非遞歸算法亂熟於心。
和二叉樹先序遍歷、中序遍歷非遞歸算法一樣,后序遍歷非遞歸算法同樣是使用棧來實現:從根結點開始,將所有最左結點全部壓棧,每當一個結點出棧時,
都先掃描該結點的右子樹,只有當一個結點的左孩子和右孩子結點均被訪問過了,才能訪問結點自身。
二叉樹后序遍歷非遞歸算法實現如下:
#include <stdlib.h> #include <stdio.h> #define MAXSIZE 100 // 定義結點類型 typedef struct node { int data; struct node* lchild; struct node* rchild; } BTnode; void Postorder(BTnode* t) { BTnode* Seqstack[MAXSIZE]; int top = -1; int falg = 1; BTnode* p; if(t != NULL) { do { while(t != NULL) // 循環,將所有最左結點壓棧 { top ++; Seqstack[top] = t; t = t->lchild; } flag = 1; // 輔助變量flag為1表示當前結點的左孩子為空或者已被訪問 p = NULL; // 指針變量p指向當前結點的前驅結點 while(top > -1&& falg == 1) { t = Seqstack[top]; // 注意:這里只是獲取棧頂元素,而並沒有出棧 if(t->rchild == p) // 如果當前結點右孩子為空,或者已經被訪問過,則訪問當前結點 { top --; // 當前結點出棧 printf("%d ", p->data); p = t; // 指針變量指向當前結點 } else // 如果當前結點右孩子不為空,則先去處理右孩子 { t = t->rchild; // 處理右孩子 flag = 0; // *t的左孩子未被訪問,flag置為0 } } }while(top > -1) } }
上面代碼實現了二叉樹后序遍歷非遞歸算法(重點看懂注釋),接下來就說一說前面提到的該算法的一個特性了:就是當訪問某個結點時,棧中所保存的元素
正好是這個結點的所有祖先。那么知道了這個特性,我們就很容易解決下面如下問題:
(1).當給定一個葉子結點,要求輸出該葉子結點的所有祖先
(2).輸出根結點到所有葉子結點的路徑
(3).如果二叉樹結點的值是數值,那么求每條路徑上值之和,也可以利用二叉樹后序遍歷的非遞歸算法這個特性