摘自: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(" 通过栈实现的中序遍历结果: "); OrderTraverseByStack(pRoot); printf(" 通过递归实现的后序遍历结果: "); PostOrderTraverse(pRoot); printf(" 通过栈实现的后序遍历结果: "); PostOrderTraverseByStack(pRoot); getchar(); return 0; }