title: 数据结构 | 树-2 | 遍历二叉树
date: 2019-12-03 13:03:42
tags: 数据结构
建树、前中后序遍历二叉树、线索二叉树
遍历二叉树
树的常见操作
建树
Status CreateBiTree(BiTree &T)
{ // 算法6.4:按先序次序输入二叉树中结点的值(可为字符型或整型,在主程中
// 定义),构造二叉链表表示的二叉树T。变量Nil表示空(子)树。有改动
TElemType ch;
cin>>ch;
if(ch==Nil) // 空
T=NULL;
else
{
T=(BiTree)malloc(sizeof(BiTNode));
if(!T)
exit(OVERFLOW);
T->data=ch; // 生成根结点
CreateBiTree(T->lchild); // 构造左子树
CreateBiTree(T->rchild); // 构造右子树
}
}
求树的深度
int BiTreeDepth(BiTree T)
{ // 初始条件: 二叉树T存在。操作结果: 返回T的深度
int i,j;
if(!T)
return 0;
if(T->lchild)
i=BiTreeDepth(T->lchild);
else
i=0;
if(T->rchild)
j=BiTreeDepth(T->rchild);
else
j=0;
return i>j?i+1:j+1;
}
插入子树
Status InsertChild(BiTree p,int LR,BiTree c) // 形参T无用
{ // 初始条件: 二叉树T存在,p指向T中某个结点,LR为0或1,非空二叉树c与T
// 不相交且右子树为空
// 操作结果: 根据LR为0或1,插入c为T中p所指结点的左或右子树。p所指结点的
// 原有左或右子树则成为c的右子树
if(p) // p不空
{
if(LR==0)
{
c->rchild=p->lchild;
p->lchild=c;
}
else // LR==1
{
c->rchild=p->rchild;
p->rchild=c;
}
return OK;
}
return ERROR; // p空
}
前序递归遍历二叉树
void PreOrderTraverse(BiTree T,Status(*Visit)(TElemType))
{ // 初始条件: 二叉树T存在,Visit是对结点操作的应用函数。算法6.1,有改动
// 操作结果: 先序递归遍历T,对每个结点调用函数Visit一次且仅一次
if(T) // T不空
{
Visit(T->data); // 先访问根结点
PreOrderTraverse(T->lchild,Visit); // 再先序遍历左子树
PreOrderTraverse(T->rchild,Visit); // 最后先序遍历右子树
}
}
前中后序的递归算法只是更改了visit(T->data)语句位置,前中后分别对应位置1、2、3
中序遍历二叉树
Status InOrderTraverse( BiTree T, status (*visit)(TElemType e )){
InitStack( S );
Push( S, T ); // 根指针进栈
while( ! StackEmpty( S )){
while( GetTop( S, p ) && p )
Push( S, p->lChild );//向左,直到最左下角
Pop( S, p ); // NULL退栈
if( !StackEmpty( S)){
Pop( S, p ); // 根退出
if( ! ( *Visit)(p->data) ) return ERROR;
Push( S, p->RChild );
}// if
}// while return OK;
}// InOrderTraverse
二叉树的计数
由二叉树的前序序列和中序序列可唯一地确定一棵二叉树。
线索二叉树
定义
前驱与后继
在二叉树的先序、中序或后序遍历序列中两个相邻的结点互称为~
线索
指向前驱或后继结点的指针称为~
线索二叉树
加上线索的二叉链表表示的二叉树叫~
线索化
对二叉树按某种遍历次序使其变为线索二叉树的过程叫~
实现
- 在有n个结点的二叉链表中必定有n+1个空链域
- 在二叉树或二叉链表中,若左孩子为空,则画出它的直接前驱,右孩子为空时,则画出它的直接后继,左右孩子不为空时,不需画前驱和后继。这样就得到了线索二叉树或线索二叉链表。
对应tag为0,child域指向孩子;
对应tag为1,child域指向孩子。
中序线索二叉树
线索二叉树的遍历
线索链表的遍历算法
附带习题
1 编写求二叉树的分枝结点个数的算法(用二叉链表存)
2 二叉树求二叉树深度算法