二叉树是 n个(n>=0)个结点的有限集合。当n=0时,称为空二叉树;当n>0时。该集合有一个根结点及两颗互不相交的,被称为左子树和右子树的二叉树组成(有点像递归定义)。也可以理解为:二叉树是满足一下两个条件的树(1)每个家结点的度不大于2,;(2)结点的子树位置是明确分左右的,不能随意改变。
二叉树的遍历在顺序上分为先序,中序和后序三种,而在方法上又分为递归和非递归两种,从结构上还有层次遍历;
(1)先序遍历二叉树的操作定义为:
若二叉树不空,则空操作,否则一次执行下列操作
访问根结点;按先序遍历左子树;按先序遍历右子树;
(2)中序遍历二叉树的操作定义为:
若二叉树不空,则空操作,否则一次执行下列操作
先按中序遍历左子树;访问根结点;再按中序遍历右子树;
(3)后序遍历二叉树的操作定义为:
若二叉树不空,则空操作,否则一次执行下列操作
先按后序遍历左子树;再按后序遍历右子树;最后访问根结点;
如图的二叉树的先中后序的遍历结果如下所示
先序:A、B、D、G、C、E、F
中序:B、G、D、A、E、C、F
后序:G、D、B、E、F、C、A
二叉树遍历的递归实现
先序遍历
</pre><pre name="code" class="cpp">void PerOrder(BiTree root)
{
if(root){
Visit(root);//访问根结点
PreOrder(root->Lchild);//先序遍历左子树
PreOrder(root->Rchild);//先序遍历右子树
}
}
中序遍历
void Order_Travarsal_Tree(BiTree root)
{
if(root){
PreOrder(root->Lchild);//先序遍历左子树
Visit(root);//访问根结点
PreOrder(root->Rchild);//先序遍历右子树
}
}
后序遍历
void PostOrder(BiTree root)
{
if(root){
PreOrder(root->Lchild);//先序遍历左子树
PreOrder(root->Rchild);//先序遍历右子树
Visit(root);//访问根结点
}
}
二叉树的非递归遍历
1. 先序非递归的实现
(1)访问根结点,根结点入栈并进入左子树,进而访问左子树的根结点并入栈,在进入下层左子树,...... ,如此重复知道当前结点为空;
(2)若栈非空,则从栈顶退出上一层结点,并进入该节点的右子树。
重复上述(1)(2)步骤,知道当前结点及栈均为空,结束
void PreOrder( BiTree root)
{
SeqStack *S;
BiTree p;
InitStack(S); p=root;
while(p!=NULL || !IsEmpty(S)){//当前节点和栈均为空,则结束
while(p!=NULL){
Visit(p->date); push(S,&p);//访问根结点,根指针入栈,进入左子树
if(!IsEmpty(S)){
Pop(S,&p); p=p->Rchild;//根指针退栈,进入右子树
}
}
}
}
2.中序非递归的实现
(1)根结点入栈,进入其左子树,进而左子树的根结点入栈,进入下一层左子树,...... ,如此重复直到当前结点为空。
(2)若栈非空,从栈顶退出上一层的结点,访问出栈结点,并进入其右子树
重复上述(1)(2)步骤,直至当前结点及栈为空,结束
void Order_Travarsal_Tree( BiTree root)
{
SeqStack *S;
BiTree p;
InitStack(S); p=root;
while(p!=NULL || !IsEmpty(S)){//当前节点和栈均为空,则结束
while(p!=NULL){
push(S,&p);p=p->Lchild;//根结点入栈,并进入左子树
}
if(!IsEmpty(S)){
Pop(S,&p);Visit(p->date); p=p->Rchild;//根指针退栈,访问上一层子树,进入右子树
}
}
}
3.后序非递归实现
(1)当前结点入栈,并进入其左子树,重复至当前结点为空
(2)若栈非空,判断栈顶结点p的右子树是否为空、右子树是否访问过,是则退栈,访问p结点,p赋值给q,p置空;否则进入p的右子树;
void PostOrder(BiTree root)
{
SeqStack *S;
BiTree p,q;
InitStack(S);
p=root;
q=NULL;
while(p!=NULL || !IsEmpty(S)){
while(p!=NULL){
Push(p);p=p->Lchild;
}
if(!IsEmptyS)){
Top(S,&p);
if(p->Rchild == NULL || p->Rchild == q){//判断右子树为空或者刚才刚问过
Pop(S,&p);
Visit(p->date);
p=q;
p=NULL;
}else
p=p->Rchild;
}
}
}
二叉树的按层遍历
二叉树的非递归遍历是用栈来实现的,而它的层遍历则是用队列来实现的,实现方式如下:
首先根结点入队,当队列非空时,重复如下两个步骤。
(1)队头结点出队,并访问对头结点。
(2)出队结点的非空左右子树一次入队。
void LevelOrder(BiTree root)
{
SeqQueue *Q;
BiTree p;
InitQueue(Q);
EnterQueue(Q,root);
while(!Isempty(Q)){
DeletQueue(Q,&p);
Visit(p->date);
if(p->Lchild != NULL)
EnterQueue(Q,p->Lchild);
if(p->Rchld != NULL)
EnterQueue(Q,p->Rchild);
}
}