您的位置:首页 > 其它

二叉树的遍历

2015-12-04 20:02 260 查看
遍历二叉树(traversing binary tree)

1.遍历二叉树的描述

遍历二叉树是指按某条搜索路径巡访树中每个结点,使得每个结点均被访问一次,而且仅被访问一次。遍历二叉树是二叉树最基本的操作,

也是二叉树其他各种操作的基础、遍历的实质是对二叉树进行线性化的过程,即遍历的结果是将非线性结构的树中结点排成一个线性序列。

1.先序遍历二叉树的操作定义如下:

若二叉树为空,则空操作,否则:

1)访问根结点;

2)先序遍历左子树;

3)先序遍历右子树;

2.中序遍历二叉树的操作定义如下:

若二叉树为空,则空操作,否则:

1)中序遍历左子树;

2)访问根结点;

3)中序遍历右子树;

3.后序遍历二叉树的操作定义如下:

若二叉树为空,则空操作,否则:

1)后序遍历左子树;

2)后序遍历右子树;

3)访问根结点;

例如,如下图所示的二叉树表示下述表达式

a+b*(c-d)-e/f



中序遍历二叉树基本操作的递归算法在二叉链表上的实现,算法将结点的访问简化为数据的输出。

中序遍历的递归算法

[算法描述]

void InOrderTraverse(BiTree T)
{
/*中序遍历二叉树T的递归算法*/
if(T)
{
InOrderTraverse(T->lchild);
cout<<T->data;
InOrderTraverse(T->rchild);
}
}
只要改变输出语句的顺序,便可类似地实现先序遍历后序遍历的递归算法。

可以利用栈将递归算法改成非递归算法,例如,从中序遍历递归算法执行过程中递归工作栈的状态可见:

1.工作记录中包含两项,其一是递归调用的语句编号,其二数指向根结点的指针,则当栈顶记录中的指针非空时,应遍历左子树,即指向左子树根的指针进栈。

2.若栈顶记录中的指针值为空,应该退至上一层,若是从左子树返回,则应访问当前层(即栈顶记录)中指针所指的根结点。

3.若是从右子树返回,则表明当前层遍历结束,应该继续退栈。从另一个角度看,这意味着遍历右子树时不需要保存当前层的根指针,直接修改栈顶记录中的指针即可。

中序遍历的非递归算法

[算法思想]

设S为一个栈,p为指向根结点的指针。

1)当p非空时,将p所指向的地址进栈,p指向该结点的左孩子

2)当p为空时,弹出栈顶元素并访问,将p指向该结点的右孩子

3)重复前两步,直到栈空且p也为空

[算法描述]

void InOrderTraverse(BiTree T)
{
/*中序遍历二叉树T的非递归算法*/
InitStack(S);p=T;
q=new BiTNode;
while(p || !StackEmpty(S) )
{
if(p)             /*p非空根指针进栈,遍历左子树*/
{
Push(S,p);
p=p->lchild;
}
else             /*p为空根指针退栈,访问根结点,遍历右子树*/
{
Pop(S,q);
cout<<q->data;
p=q->rchild;
}
}
}


2.根据遍历序列确定二叉树

由二叉树的先序序列中序序列,或由其后序序列和中序序列均能唯一确定一棵二叉树。

例如,已知一棵二叉树的中序序列和后序序列分别是
BDCEAFHGDECBHGFA,请画出这棵二叉树。

[解题思路]

1)由后序遍历特征,根结点必在后序序列尾部,即根结点是A;

2)由中序遍历特征,根结点必在其中间,而且其左部必全部是左子树子孙(BDCE),其右部必全部是右子树子孙(FHG).

3)继而,根据后序中的DECB子树可确定B为A的左孩子,根据HGF子串可确定F为A的右孩子;依次类推,可以唯一确定一棵二叉树。

但是,由一棵二叉树的先序序列和后序序列不能唯一确定一棵二叉树,因为无法确定左右子树两部分。



例如,如果有先序序列AB,后序序列BA,因为无法确定B为左子树还是右子树,所以可得到图所示的两颗不用的二叉树。



3.二叉树遍历算法的应用


“遍历”是二叉树各种操作的基础,假设访问结点的具体操作不仅仅局限于输出结点数据域的值,而把“访问”延伸到对结点的判别、计数等其他操作

,可以解决一些关于二叉树的其他实际问题。如在遍历过程中生成结点,这样便可以建立二叉树的存储结构。

1)创建二叉树的存储结构——二叉链表

为简化问题,设二叉树中结点的元素均为一个单字符。假设按先序遍历的顺序建立二叉链表,T为指向根结点的指针:首先输入一个根结点,若输入是一个

“#”字符,则表明该二叉树为空树,即T为NULL;否则输入的该字符赋给T->data,之后依次递归建立它的左子树T->lchild和右子树T->rchild。例如下图,读入

字符的顺序为:ABC ## DE # G ## F ###(其中#表示空树),可建立相应的二叉链表。



先序遍历的顺序建立二叉链表

[算法描述]

void CreateBiTree(BiTree &T)
{
/*按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T*/
cin>>ch;
if(ch == '#') T=NULL;
else
{
T=new BiTNode;
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}


2)计算二叉树的深度

二叉树的深度为树中结点的最大层次。如果是空树,则深度为0;否则,递归计算左子树的深度记为m,递归计算右子树的深度记为n,二叉树的深度则为m

与n的较大者加1.显然,这是在后序遍历二叉树的基础上进行的运算。

[算法描述]

int Depth(BiTree T)
{
if(T == NULL) return 0;    /*如果是空树,深度为0,递归结束*/
else
{
m=Depth(T->lchild);   /*递归计算左子树的深度记为m*/
n=Depth(T->rchild);   /*递归计算右子树的深度记为n*/
return m>n?m+1:n+1;   /*二叉树的深度为m与n的较大者加1*/
}
}


3)统计二叉树中结点的个数

如果是空树,则结点个数为0;否则,结点个数为 左子树的结点个数加上右子树的结点个数再加上1。

[算法描述]

int NodeCount(BiTree T)
{
if(T == NULL)return 0;         /*如果是空,则结点个数为0,递归结束*/
else                           /*否则结点个数为左子树的结点个数+右子树的结点个数+1*/
{
return NodeCount(T->lchild)+NodeCount(T->rchild)+1;
}
}

[完整代码]

#include<iostream>
using namespace std;
typedef struct BiTNode
{
char data; /*结点数据域*/
struct BiTNode *lchild,*rchild; /*左右孩子指针*/
}BiTNode,*BiTree;
int n,m;
void CreateBiTree(BiTree &T)
{
char ch;
/*按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T*/
cin>>ch;
if(ch == '#') T=NULL;
else
{
T=new BiTNode;
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
int Depth(BiTree T) { if(T == NULL) return 0; /*如果是空树,深度为0,递归结束*/ else { m=Depth(T->lchild); /*递归计算左子树的深度记为m*/ n=Depth(T->rchild); /*递归计算右子树的深度记为n*/ return m>n?m+1:n+1; /*二叉树的深度为m与n的较大者加1*/ } }
int NodeCount(BiTree T) { if(T == NULL)return 0; /*如果是空,则结点个数为0,递归结束*/ else /*否则结点个数为左子树的结点个数+右子树的结点个数+1*/ { return NodeCount(T->lchild)+NodeCount(T->rchild)+1; } }
void InOrderTraverse(BiTree T)
{
/*中序遍历二叉树T的递归算法*/
if(T)
{
InOrderTraverse(T->lchild);
cout<<T->data<<" ";
InOrderTraverse(T->rchild);
}
}
int main()
{
BiTree T;
cout<<"Input the Binary Tree 's node:"<<endl;
/*sample input:ABC ## DE # G ## F ###*/
CreateBiTree(T);
cout<<"InOrderTraverse: "<<endl;
InOrderTraverse(T);
cout<<"\nThe Depth:"<<Depth(T)<<"\t The sum's node:"<<NodeCount(T)<<endl;
getchar();
return 0;
}
[运行结果]




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: