#include "stdafx.h"
#include <iostream>
#include <stack>
#include <queue>
//定义二叉树(二叉链表表示法)的节点
typedef struct BiTNode
{
char data;//数据域
struct BiTNode * lchild;//指向左子树
struct BiTNode * rchild;//指向右子树
} BiTNode, * BiTree;
/下面为辅助函数//
BiTree createBiTNode(char data)
{
BiTree p=(BiTree) malloc(sizeof(BiTNode));
if(p!=NULL)
{
p->data=data;
p->lchild=NULL;
p->rchild=NULL;
return p;
}
return NULL;
}
void createLChild(BiTree & parent,BiTree & lchild)
{
parent->lchild=lchild;
}
void createRChild(BiTree & parent,BiTree & rchild)
{
parent->rchild=rchild;
}
//由于主要讨论遍历所以随意创建一颗二叉树
//创建一颗如图所示的二叉树
// A
// /
// B
// / \
// C D
// / \
// E F
// \
// G
BiTree createBiTree()
{
BiTree Pa=createBiTNode('A');
BiTree Pb=createBiTNode('B');
BiTree Pc=createBiTNode('C');
BiTree Pd=createBiTNode('D');
BiTree Pe=createBiTNode('E');
BiTree Pf=createBiTNode('F');
BiTree Pg=createBiTNode('G');
createLChild(Pa,Pb);
createLChild(Pb,Pc);
createRChild(Pb,Pd);
createLChild(Pd,Pe);
createRChild(Pd,Pf);
createRChild(Pe,Pg);
return Pa;
}
//摧毁二叉树
//这里定义的是递归摧毁,也可以定义非递归摧毁
void DestoryBiTree(BiTree t)
{
if(t!=NULL)
{
BiTree plchild=t->lchild;
BiTree prchild=t->rchild;
free(t);
DestoryBiTree(plchild);
DestoryBiTree(prchild);
}
}
//定义一个全局访问函数//
void vist(char data)
{
std::cout<<data<<" ";
}
下面是递归遍历算法///
//先序递归遍历算法///
void PreOrderTraverse(BiTree t)
{
if(t!=NULL)
{
vist(t->data);//遍历根节点
PreOrderTraverse(t->lchild);//先序遍历左子树
PreOrderTraverse(t->rchild);//先序遍历右子树
}
}
//中序递归遍历算法/
void InOrderTraverse(BiTree t)
{
if(t!=NULL)
{
InOrderTraverse(t->lchild);//中序遍历左子树
vist(t->data);//遍历根节点
InOrderTraverse(t->rchild);//中序遍历右子树
}
}
//后序递归遍历算法/
void PostOrderTraverse(BiTree t)
{
if(t!=NULL)
{
PostOrderTraverse(t->lchild);//后序遍历左子树
PostOrderTraverse(t->rchild);//后序遍历右子树
vist(t->data);//遍历根节点
}
}
///
下面是非递归遍历算法//
//先序非递归遍历算法
//思路
//对于任一结点P:
// 1)访问结点P,并将结点P入栈;
// 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;
// 3)直到P为NULL并且栈为空,则遍历结束。
void Nonrecursive_PreOrderTraverse(BiTree t)
{
std::stack<BiTree> stack;//定义一个栈
BiTree p=t;
BiTree q;
while(p!=NULL || !stack.empty())
{
if(p!=NULL)
{
//访问数据/
vist(p->data);
/
stack.push(p);
p=p->lchild;
}
else
{
q=stack.top();
stack.pop();
p=q->rchild;
}
}
}
//中序非递归遍历算法
//思路:
// 对于任一结点P,
// 1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;
// 2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;
// 3)直到P为NULL并且栈为空则遍历结束
void Nonrecursive_InOrderTraverse(BiTree t)
{
std::stack<BiTree> stack;//定义一个栈
BiTree p=t;
BiTree q;
while(p!=NULL || !stack.empty())
{
if(p!=NULL)
{
stack.push(p);
p=p->lchild;
}
else
{
q=stack.top();
stack.pop();
//访问数据/
//跟先序其他都一样只是访问数据操作的时机不同
vist(q->data);
///
p=q->rchild;
}
}
}
//非递归后序遍历的算法较复杂
//-------重点---------
//后序非递归遍历算法
//思路一
//对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,
//直到搜索到没有左孩子的结点,此时该结点出现在栈顶,
//但是此时不能将其出栈并访问,因此其右孩子还为被访问。
//所以接下来按照相同的规则对其右子树进行相同的处理,
//当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。
//这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,
//只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。
typedef struct PostTraNode
{
BiTree p;//指向二叉树节点的指针
bool isPop;//下次出现在栈顶是是否应该出栈
}PostTraNode;
void Nonrecursive_PostOrderTraverse1(BiTree t)
{
BiTree p=t;
std::stack <PostTraNode *> stack;
while(p!=NULL || !stack.empty())
{
if(p!=NULL)
{
PostTraNode * pPost=(PostTraNode *)malloc(sizeof(PostTraNode));
if(pPost)
{
pPost->isPop=false;
pPost->p=p;
}
stack.push(pPost);
p=p->lchild;
}
else
{
PostTraNode * pPost=stack.top();
if(pPost->isPop)//可以出栈,即可以访问该节点
{
stack.pop();
vist(pPost->p->data);
}
else
{
pPost->isPop=true;
p=pPost->p->rchild;
}
}
}
}
//思路二
//要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,
//先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;
//或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,
//则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,
//这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,
//左孩子和右孩子都在根结点前面被访问。
void Nonrecursive_PostOrderTraverse2(BiTree t)
{
if(t==NULL)
return;
BiTree cur;
BiTree pre=NULL;//上一次访问的节点
std::stack<BiTree> stack;
stack.push(t);
while(!stack.empty())
{
cur=stack.top();
if((cur->lchild==NULL && cur->rchild==NULL) || (pre!=NULL && (cur->lchild==pre || cur->rchild==pre)))
{
stack.pop();
vist(cur->data);
pre=cur;
}
else
{
if((cur->rchild)!=NULL)
stack.push(cur->rchild);
if((cur->lchild)!=NULL)
stack.push(cur->lchild);
}
}
}
//按层从上到下,从左到右遍历
void Nonrecursive_LayerOrderTraverse(BiTree t)
{
if(t==NULL)
return;
std::queue<BiTree> queue;//定义一个队列
BiTree p=t;
queue.push(p);
while(!queue.empty())
{
p=queue.front();
queue.pop();
vist(p->data);
if(p->lchild != NULL)
queue.push(p->lchild);
if(p->rchild != NULL)
queue.push(p->rchild);
}
}
//求二叉树的深度/
int max(int x,int y)
{
return x>y ? x : y;
}
递归算法
int BiTreeDepth(BiTree t)
{
if(t==NULL)
return 0;
else
return 1+max(BiTreeDepth(t->lchild),BiTreeDepth(t->rchild));
}
非递归实现
int Nonrecursive_BiTreeDepth(BiTree t)
{
if(t==NULL)
return 0;
int depth=1;
std::queue<BiTree> queue;
BiTree p=t;
queue.push(p);
queue.push(NULL);//NULL标志一层结束
while(queue.size()>1)
{
p=queue.front();
queue.pop();
if(p!=NULL)
{
if(p->lchild!=NULL)
queue.push(p->lchild);
if(p->rchild!=NULL)
queue.push(p->rchild);
}
else
{
++depth;
queue.push(NULL);
}
}
return depth;
}
int _tmain(int argc, _TCHAR* argv[])
{
BiTree t=createBiTree();
PreOrderTraverse(t);
std::cout<<std::endl;
InOrderTraverse(t);
std::cout<<std::endl;
PostOrderTraverse(t);
std::cout<<std::endl;
std::cout<<BiTreeDepth(t)<<std::endl;
std::cout<<"非递归遍历结果余下"<<std::endl;
Nonrecursive_PreOrderTraverse(t);
std::cout<<std::endl;
Nonrecursive_InOrderTraverse(t);
std::cout<<std::endl;
Nonrecursive_PostOrderTraverse1(t);
std::cout<<std::endl;
Nonrecursive_PostOrderTraverse2(t);
std::cout<<std::endl;
Nonrecursive_LayerOrderTraverse(t);
std::cout<<std::endl;
std::cout<<Nonrecursive_BiTreeDepth(t)<<std::endl;
std::cout<<std::endl;
DestoryBiTree(t);
system("PAUSE");
return 0;
}
参考资料: 数据结构(C语言版)严蔚敏 P126——P131