/************************************************************************/
/* 程序:二叉树的递归遍历与非递归遍历 */
/* 开发语言:C++ */
/* 关键词:二叉树,先序,中序,后续,层次,遍历,递归,非递归 */
/* 作者:万山居(wanshanju#gmail.com) */
/* 参考资料: */
/* (1) <<数据结构>> 清华大学出版社 严蔚敏著 */
/* (2) http://bbs.chinaunix.net/viewthread.php?tid=331522 */
/* (3) http://www.programfan.com/blog/article.asp?id=19799 */
/************************************************************************/
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
typedef char NodeData;
struct BinaryTreeNode
{
NodeData Data;
BinaryTreeNode * LeftChild;
BinaryTreeNode * RightChild;
};
typedef BinaryTreeNode * BinaryTree;
// 带有标志位的节点
struct FlagNode
{
BinaryTreeNode * Node;
int Flag; //标志位
FlagNode(){}
FlagNode(BinaryTreeNode * node,int flag):Node(node),Flag(flag){}
};
enum FlagType
{
VisitLeftChild,
VisitRightChild,
VisitCurrentNode,
CanVisit,
CanNotVisit
};
void Visit(const NodeData &data)
{
cout<<data<<' ';
}
// 先序遍历二叉树的递归算法
void PreOrderTraverseRecursive(BinaryTree tree)
{
if(tree)
{
Visit(tree->Data);
PreOrderTraverseRecursive(tree->LeftChild);
PreOrderTraverseRecursive(tree->RightChild);
}
}
// 先序遍历二叉树的非递归算法
void PreOrderTraverseNoRecursive1(BinaryTree tree)
{
stack<BinaryTree> stackA;
BinaryTree node;
stackA.push(tree);
int popCount = 0;
while (!stackA.empty())
{
while( (node = stackA.top()) )
{
Visit(node->Data);
stackA.push(node->LeftChild);
}
// 空节点退栈
stackA.pop();
++popCount;
if(!stackA.empty())
{
node = stackA.top();
stackA.pop();
++popCount;
stackA.push(node->RightChild);
}
}
printf("(popCount %d)",popCount);
}
// 先序遍历二叉树的非递归算法(较好的先序非递归)
void PreOrderTraverseNoRecursive2(BinaryTree tree)
{
if(!tree) return;
stack<BinaryTree> stackA;
BinaryTree node;
stackA.push(tree);
int popCount = 0;
while (!stackA.empty())
{
node = stackA.top();
stackA.pop();
++popCount;
Visit(node->Data);
// 先右子树入栈,后左子树入栈
if(node->RightChild) stackA.push(node->RightChild);
if(node->LeftChild) stackA.push(node->LeftChild);
}
printf("(popCount %d)",popCount);
}
// 先序遍历二叉树的非递归算法
void PreOrderTraverseNoRecursive3(BinaryTree tree)
{
if(!tree) return;
stack<FlagNode> stackA;
FlagNode node;
node.Node = tree;
node.Flag = CanNotVisit;
stackA.push(node);
int popCount = 0;
while (!stackA.empty())
{
node = stackA.top();
stackA.pop();
++popCount;
if(node.Flag == CanVisit)
{
Visit(node.Node->Data);
}
else
{
if(node.Node->RightChild)
{
stackA.push(FlagNode(node.Node->RightChild,CanNotVisit));
}
if(node.Node->LeftChild)
{
stackA.push(FlagNode(node.Node->LeftChild,CanNotVisit));
}
node.Flag = CanVisit;
stackA.push(node);
}
}
printf("(popCount %d)",popCount);
}
// 中序遍历二叉树的递归算法
void InOrderTraverseRecursive(BinaryTree tree)
{
if(tree)
{
InOrderTraverseRecursive(tree->LeftChild);
Visit(tree->Data);
InOrderTraverseRecursive(tree->RightChild);
}
}
// 中序遍历二叉树的非递归算法
void InOrderTraverseNoRecursive1(BinaryTree tree)
{
stack<BinaryTree> stackA;
BinaryTree node;
stackA.push(tree);
int popCount = 0;
while (!stackA.empty())
{
//向左走到尽头
while( (node = stackA.top()) )
{
stackA.push(node->LeftChild);
}
// 空节点退栈
stackA.pop();
++popCount;
// 访问节点,向右一步
if(!stackA.empty())
{
node = stackA.top();
Visit(node->Data);
stackA.pop();
++popCount;
stackA.push(node->RightChild);
}
}
printf("(popCount %d)",popCount);
}
// 中序遍历二叉树的非递归算法,(较好的中序非递归)
// 比非递归算法少了些push和pop,因此遍历速度更快
void InOrderTraverseNoRecursive2(BinaryTree tree)
{
stack<BinaryTree> stackA;
BinaryTree node = tree;
int popCount = 0;
while (node || !stackA.empty())
{
// 向左走一步
if(node)
{
stackA.push(node);
node = node->LeftChild;
}
else
{
// 节点退栈
node = stackA.top();
stackA.pop();
++popCount;
// 访问节点
Visit(node->Data);
node = node->RightChild;
}
}
printf("(popCount %d)",popCount);
}
// 中序遍历二叉树的非递归算法
void InOrderTraverseNoRecursive3(BinaryTree tree)
{
if(!tree) return;
stack<FlagNode> stackA;
FlagNode node;
node.Node = tree;
node.Flag = CanNotVisit;
stackA.push(node);
int popCount = 0;
while (!stackA.empty())
{
node = stackA.top();
stackA.pop();
++popCount;
if(node.Flag == CanVisit)
{
Visit(node.Node->Data);
}
else
{
if(node.Node->RightChild)
{
//右子树入栈且置访问标志为CanNotVisit
stackA.push(FlagNode(node.Node->RightChild,CanNotVisit));
}
node.Flag = CanVisit;
stackA.push(node);
if(node.Node->LeftChild)
{
//左子树入栈且置访问标志为CanNotVisit
stackA.push(FlagNode(node.Node->LeftChild,CanNotVisit));
}
}
}
printf("(popCount %d)",popCount);
}
// 后序遍历二叉树的递归算法
void PostOrderTraverseRecursive(BinaryTree tree)
{
if(tree)
{
PostOrderTraverseRecursive(tree->LeftChild);
PostOrderTraverseRecursive(tree->RightChild);
Visit(tree->Data);
}
}
// 后序遍历二叉树的非递归算法
void PostOrderTraverseNoRecursive1(BinaryTree tree)
{
stack<FlagNode> stackA;
FlagNode node;
node.Node = tree;
node.Flag = VisitLeftChild;
if (node.Node)
{
stackA.push(node);
}
int popCount = 0;
while (!stackA.empty())
{
node = stackA.top();
stackA.pop();
++popCount;
switch(node.Flag)
{
case VisitLeftChild:
node.Flag = VisitRightChild;
stackA.push(node);
if(node.Node->LeftChild)
{
node.Node = node.Node->LeftChild;
node.Flag = VisitLeftChild;
stackA.push(node);
}
break;
case VisitRightChild:
node.Flag = VisitCurrentNode;
stackA.push(node);
if(node.Node->RightChild)
{
node.Node = node.Node->RightChild;
node.Flag = VisitLeftChild;
stackA.push(node);
}
break;
case VisitCurrentNode:
Visit(node.Node->Data);
break;
}
}
printf("(popCount %d)",popCount);
}
// 后序遍历二叉树的非递归算法(较好的后序非递归)
void PostOrderTraverseNoRecursive2(BinaryTree tree)
{
if(!tree) return;
stack<FlagNode> stackA;
FlagNode node;
node.Node = tree;
node.Flag = CanNotVisit;
stackA.push(node);
int popCount = 0;
while (!stackA.empty())
{
node = stackA.top();
stackA.pop();
++popCount;
if(node.Flag == CanVisit)
{
Visit(node.Node->Data);
}
else
{
node.Flag = CanVisit;
stackA.push(node);
if(node.Node->RightChild)
{
stackA.push(FlagNode(node.Node->RightChild,CanNotVisit));
}
if(node.Node->LeftChild)
{
stackA.push(FlagNode(node.Node->LeftChild,CanNotVisit));
}
}
}
printf("(popCount %d)",popCount);
}
// 层次遍历二叉树,使用队列
void HierarchyTraverse(BinaryTree tree)
{
if(!tree) return;
queue<BinaryTree> nodeQueue;
BinaryTree pNode = NULL;
nodeQueue.push(tree);
while (!nodeQueue.empty())
{
pNode = nodeQueue.front();
nodeQueue.pop();
Visit(pNode->Data);
if (pNode->LeftChild) nodeQueue.push(pNode->LeftChild);
if (pNode->RightChild) nodeQueue.push(pNode->RightChild);
}
}
// 创建二叉树,按先序遍历方式创建
// 字符'#'表示空节点
void CreateBinaryTree(BinaryTree &tree)
{
char ch;
cin>>ch;
cout<<ch<<' ';
if(ch == '#')
{
tree = NULL;
}
else
{
tree = (BinaryTreeNode *)malloc(sizeof(BinaryTreeNode));
tree->Data = ch;
CreateBinaryTree(tree->LeftChild);
CreateBinaryTree(tree->RightChild);
}
}
// 销毁二叉树,释放内存
void DestroyBinaryTree(BinaryTree & tree)
{
if(tree)
{
DestroyBinaryTree(tree->LeftChild);
DestroyBinaryTree(tree->RightChild);
Visit(tree->Data);
free(tree);
}
}
/* 测试代码
输入数据:
A
B
D
#
#
E
#
#
C
F
#
#
#
输出数据:
CreateBinaryTree:
A B D # # E # # C F # # #
PreOrder:
PreOrderTraverseRecursive:
A B D E C F
PreOrderTraverseNoRecursive1:
A B D E C F (popCount 13)
PreOrderTraverseNoRecursive2:
A B D E C F (popCount 6)
PreOrderTraverseNoRecursive3:
A B D E C F (popCount 12)
InOrder:
InOrderTraverseRecursive:
D B E A F C
InOrderTraverseNoRecursive1:
D B E A F C (popCount 13)
InOrderTraverseNoRecursive2:
D B E A F C (popCount 6)
InOrderTraverseNoRecursive3:
D B E A F C (popCount 12)
PostOrder:
PostOrderTraverseRecursive:
D E B F C A
PostOrderTraverseNoRecursive1:
D E B F C A (popCount 18)
PostOrderTraverseNoRecursive2:
D E B F C A (popCount 12)
HierarchyTraverse:
A B C D E F
DestroyBinaryTree:
D E B F C A
*/
int main()
{
// 创建二叉树
BinaryTree tree = NULL;
printf("CreateBinaryTree:/n");
CreateBinaryTree(tree);
// 先序遍历
printf("/n/nPreOrder:");
printf("/nPreOrderTraverseRecursive:/n");
PreOrderTraverseRecursive(tree);
printf("/nPreOrderTraverseNoRecursive1:/n");
PreOrderTraverseNoRecursive1(tree);
printf("/nPreOrderTraverseNoRecursive2:/n");
PreOrderTraverseNoRecursive2(tree);
printf("/nPreOrderTraverseNoRecursive3:/n");
PreOrderTraverseNoRecursive3(tree);
printf("/n");
// 中序遍历
printf("/n/nInOrder:");
printf("/nInOrderTraverseRecursive:/n");
InOrderTraverseRecursive(tree);
printf("/nInOrderTraverseNoRecursive1:/n");
InOrderTraverseNoRecursive1(tree);
printf("/nInOrderTraverseNoRecursive2:/n");
InOrderTraverseNoRecursive2(tree);
printf("/nInOrderTraverseNoRecursive3:/n");
InOrderTraverseNoRecursive3(tree);
// 后续遍历
printf("/n/nPostOrder:");
printf("/nPostOrderTraverseRecursive:/n");
PostOrderTraverseRecursive(tree);
printf("/nPostOrderTraverseNoRecursive1:/n");
PostOrderTraverseNoRecursive1(tree);
printf("/nPostOrderTraverseNoRecursive2:/n");
PostOrderTraverseNoRecursive2(tree);
// 层次遍历
printf("/n/nHierarchyTraverse:/n");
HierarchyTraverse(tree);
// 销毁二叉树
printf("/n/nDestroyBinaryTree:/n");
DestroyBinaryTree(tree);
return 0;
}