二叉树的遍历
来源:互联网 发布:c语言大于号怎么打 编辑:程序博客网 时间:2024/06/05 07:36
遍历二叉树(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.根据遍历序列确定二叉树
由二叉树的先序序列和中序序列,或由其后序序列和中序序列均能唯一确定一棵二叉树。
例如,已知一棵二叉树的中序序列和后序序列分别是 BDCEAFHG 和 DECBHGFA,请画出这棵二叉树。
[解题思路]
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;}[运行结果]
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- 二叉树的遍历
- Java查找数组中的最小值
- 计算机网络(浅谈FTP协议)
- Thrift C++ Server demo 实现
- bzoj1188 分裂游戏 博弈论
- 微信分享标题和图片设置
- 二叉树的遍历
- if语句实现分支结构 课后习题
- uva 10700 Camel trading (水贪心+栈)
- 学习GIT
- VC维
- 【Html】认识<hr>标签,添加水平横线
- iOS开发——高德地图调研(路线规划,周边搜索,)
- CAAnimationGroup的简单使用
- (1)轻松构建DuiLib HelloWorld By DuiCreator(上)