摘自:https://blog.csdn.net/cocoiehl/article/details/80959143
https://bbs.csdn.net/topics/391882020
(只是為了方便自己復習)

一般我們遍歷二叉樹的時候用的是遞歸,用遞歸實現比較簡單,代碼如下:
/****************
基於遞歸實現后序遍歷,
*****************/
void PostOrderTraverse(NODE* pRoot) {
if (pRoot == NULL) {
return;
}
else {
PostOrderTraverse(pRoot->pLeft);
PostOrderTraverse(pRoot->pRight);
printf("%c", pRoot->chValue);
}
return;
}
通過改變printf語句的位置便可以實現前序和中序遍歷。
下面我們來看看如何基於棧實現二叉樹的遍歷,可以把二叉樹分為root,left,right三個部分
前序遍歷的次序為root,left,right;
中序遍歷的次序為left,root,right;
后序遍歷的次序為left,right,root;
先討論前序遍歷和中序遍歷,顯然可以通過下面的步驟實現
1.不斷將左子樹入棧,直到左子樹為空
2.不斷出棧,直到出棧元素的右子樹不為空
3.如果棧不為空或當前根結點不為空,重復步驟1和2
前序遍歷是在步驟1中將入棧的樹的根結點輸出,而中序則是在步驟2中將出棧的樹的根結點輸出
代碼如下:
/****************
基於棧實現前序和中序遍歷
*****************/
void OrderTraverseByStack(NODE* pRoot) {
NODE* Stack[1000];
int top = 0;
while (top > 0 || pRoot != NULL) {
for (; pRoot != NULL; pRoot = pRoot->pLeft) {
Stack[top++] = pRoot;
//前序遍歷
//printf("%c",pRoot->chValue);
}
for (; pRoot == NULL&&top > 0; pRoot = pRoot->pRight) {
pRoot = Stack[--top];
//中序遍歷
//printf("%c", pRoot->chValue);
}
}
}
最后要如何基於棧實現二叉樹的后序遍歷呢?通過觀察可以發現
前序遍歷的次序為root,left,right;
后序遍歷的次序為left,right,root;
將前序遍歷的left和right調換,在倒過來輸出,便可以實現后序遍歷!
因此我們可以通過修改一下上面的代碼實現后序遍歷,方法如下:
1,將前序遍歷代碼中的left 和right 對調,並數據存在棧S中。
2,前序遍歷完后,將棧S中的數據逐個出棧並打印即可。
代碼如下:
/****************
基於棧實現后序遍歷
*****************/
void PostOrderTraverseByStack(NODE* pRoot) {
NODE *StackA[1000],*StackB[1000];
int topA = 0,topB = 0;
while (topA > 0 || pRoot != NULL) {
for (; pRoot != NULL;pRoot = pRoot->pRight) {
StackA[topA++] = pRoot;
StackB[topB++] = pRoot;
}
for (; pRoot == NULL&&topA > 0; pRoot = pRoot->pLeft) {
pRoot = StackA[--topA];
}
}
while (topB > 0) {
printf("%c", StackB[--topB]->chValue);
}
}
下面是測試代碼:
#include<stdio.h>
#include<stdlib.h>
#define TREELEN 6
struct NODE {
NODE* pLeft;
NODE* pRight;
char chValue;
};
void ReBuild(char* pPreOrder,char* pInOrder,int nTreeLen,NODE** pRoot) {
if (pPreOrder == NULL || pInOrder == NULL) {
return;
}
NODE* pTemp =(NODE* )malloc(sizeof(NODE));
pTemp->chValue = *pPreOrder;
pTemp->pLeft = NULL;
pTemp->pRight = NULL;
if (*pRoot == NULL) {
*pRoot = pTemp;
}
if (nTreeLen == 1) {
return;
}
char* pOrgInOrder = pInOrder;
char* pLeftEnd = pInOrder;
int nTempLen = 0;
while (*pPreOrder != *pLeftEnd) {
if (pPreOrder == NULL || pLeftEnd == NULL) {
return;
}
nTempLen++;
if (nTempLen > nTreeLen) {
break;
}
pLeftEnd++;
}
int nLeftLen = 0;
nLeftLen = (int)(pLeftEnd - pOrgInOrder);
int nRightLen = 0;
nRightLen = nTreeLen - nLeftLen - 1;
if (nLeftLen > 0) {
ReBuild(pPreOrder+1, pInOrder, nLeftLen, &((*pRoot)->pLeft));
}
if (nRightLen > 0) {
ReBuild(pPreOrder + nLeftLen + 1, pInOrder + nLeftLen +1, nRightLen, &((*pRoot)->pRight));
}
}
/****************
基於遞歸實現后序遍歷,
*****************/
void PostOrderTraverse(NODE* pRoot) {
if (pRoot == NULL) {
return;
}
else {
PostOrderTraverse(pRoot->pLeft);
PostOrderTraverse(pRoot->pRight);
printf("%c", pRoot->chValue);
}
return;
}
/****************
基於棧實現前序和中序遍歷
*****************/
void OrderTraverseByStack(NODE* pRoot) {
NODE* Stack[1000];
int top = 0;
while (top > 0 || pRoot != NULL) {
for (; pRoot != NULL; pRoot = pRoot->pLeft) {
Stack[top++] = pRoot;
//前序遍歷
//printf("%c",pRoot->chValue);
}
for (; pRoot == NULL&&top > 0; pRoot = pRoot->pRight) {
pRoot = Stack[--top];
//中序遍歷
printf("%c", pRoot->chValue);
}
}
}
/****************
基於棧實現后序遍歷
*****************/
void PostOrderTraverseByStack(NODE* pRoot) {
NODE *StackA[1000],*StackB[1000];
int topA = 0,topB = 0;
while (topA > 0 || pRoot != NULL) {
for (; pRoot != NULL;pRoot = pRoot->pRight) {
StackA[topA++] = pRoot;
StackB[topB++] = pRoot;
}
for (; pRoot == NULL&&topA > 0; pRoot = pRoot->pLeft) {
pRoot = StackA[--topA];
}
}
while (topB > 0) {
printf("%c", StackB[--topB]->chValue);
}
}
int main() {
NODE* pRoot = NULL;
char pre[TREELEN] = { 'a','b','d','e','c','f' };
char in[TREELEN] = { 'd','b','e','a','f','c' };
ReBuild(pre, in, TREELEN, &pRoot);
printf("\n通過棧實現的中序遍歷結果:\n");
OrderTraverseByStack(pRoot);
printf("\n通過遞歸實現的后序遍歷結果:\n");
PostOrderTraverse(pRoot);
printf("\n通過棧實現的后序遍歷結果:\n");
PostOrderTraverseByStack(pRoot);
getchar();
return 0;
}
