文章目录
二叉树(有关遍历补充+代码)
补充
先序遍历和中序遍历有一些小诀窍
先序遍历:这样子一画就可以找到先序遍历为ABDEC
中序遍历:DBEAC(缺点,画的二叉树必须画的很标准,不然很难看出来哦)
代码
链式存储结构:
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
中序遍历的递归算法
void InOrderTraverse(BiTree T)
{//中序遍历二叉树T的4递归算法
if(T) //二叉树非空
{
InOrderTraverse(T->lchild); //中序遍历左子树
cout<<T->data; //访问根结点
InOrderTraverse(T->rchild); //中序遍历右子树
}
}
中序遍历的非递归算法
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; //遍历右子树
}
}
}
二叉树按层次遍历(用队列实现)
先序遍历建立二叉链表
void CreateBiTree(BiTree &T)
{//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树
cin>>ch;
if(ch=='#') T=NULL; //递归结束,建立空树
else //递归建立二叉树
{
T=new BiTNode; //生成根结点
T->data=ch;
CreateBiTree(T->lchild);//递归创建左子树
CreateBiTree(T->rchile);//递归创建右子树
}
}
复制二叉树
void Copy(BiTree T,BiTree &NewT)
{//复制一棵和T完全相同的二叉树
if(T==NULL) //如果是空树,递归结束
{
NewT=NULL;
return;
}
else
{
NewT=new BiTNode;
NewT->data=T->data; //复制根结点
Copy(T->lchild,NewT->lchild); //递归复制左子树
Copy(T->rchild,NewT->rchild); //递归复制右子树
}
}
计算二叉树的深度
int Depth(BiTree T)
{//计算二叉树的深度
if(T==NULL) return 0; //如果是空树,深度为0,递归结束
else
{
m=Depth(T->lchild); //递归计算左子树的深度记为m
n=Depth(T->rchild); //递归计算右子树的深度记为n
if(m<n) return (m+1); //二叉树的深度为m和n的较大者+1****
else return (n+1);
}
}
统计二叉树中结点的个数
int NodeCount(BiTree T)
{//统计二叉树T中结点的个数
if(T==NULL) return 0; //如果是空树,结点数为0,递归结束
else return NodeCount(T->lchild)+NodeCount(T->rchild)+1;
//否则结点数为左子树的结点个数+右子树的结点个数再+1
}
线索二叉树
一些概念和构造解析
一些小概念
- 引入线索二叉树来保存前驱后继的信息
- 线索二叉树的结点形式
- 规定:Tag为0说明有孩子(左孩子,右孩子),Tag为1说明是前驱(LTag=1)或者是后继(RTag=1)
- 线索二叉树:二叉树加上线索(指向结点的前驱或者后继的指针)
- 对二叉树以某种遍历使其变成线索二叉树的过程叫做线索化
构造线索二叉树的过程解析
线索化过程就是在遍历过程中修改空指针(将空指针指向前驱或后继)的过程。
线索化二叉树的约定
- 头结点:
LTag=0,lchild指向根
RTag=1,rchild指向最后一点 - 序列第一点若左为空 LTag=1,lchild->头结点
- 序列最后一点若右为空 RTag=1,rchild->头结点
例子:画出以下二叉树对应的中序线索二叉树
先写出中序遍历:HDIBEAFCG
然后根据中序遍历就可以画出中序线索二叉树
线索链表:
有头结点,头结点前驱指向二叉树的根,后继指向G;H的前驱指向头结点,G的后继指向头结点
代码
二叉树的二叉线索存储表示
二叉树的二叉线索存储表示
typedef struct BiThrNode
{
TElemType data;
struct BiThrNode *lchild,*rchild; //左右孩子指针
int LTag,RTag; //左右标志
}BiThrNode,*BiThrTree;
以结点p为根的子树中序线索化
void InThreading(BiThrTree p)
{//pre是全局变量,初始化时其右孩子指针为空,便于在树的最左点开始建线索
if(p)
{
InThreading(p->lchild); //左子树递归线索化
if(!p->lchild) //p的左孩子为空
{
p->LTag=1; //给p加上左线索
p->lchild=pre; //p的左孩子指针指向pre
}
else p->LTag=0;
if(!pre->rchild) //pre的右孩子为空
{
pre->RTag=1; //给pre加上右线索
pre->rchild=p; //pre的右孩子指向p
}
else pre->RTag=0;
pre=p; //保持pre指向p的前驱
InThreading(p->rchild); //右子树递归线索化
}
}
带头结点的二叉树中序线索化
void InOrderThreading(BiThrTree &Thrt , BiThrTree T)
{//中序遍历二叉树T,并将其中序线索化,Thrt指向头结点
Thrt = new BiThrNode; //建头结点
Thrt->LTag=0; //头结点有左孩子,若树非空,则其左孩子为树根
Thrt->RTag=1; //头结点的右孩子为右线索
Thrt->rchild=Thrt; //初始化的时候右指针指向自己
if(!T) Thrt->lchild=Thrt; //若树为空,则左指针也指向自己
else
{
Thrt->lchild=T; pre=Thrt;//头结点的左孩子指向根,pre初值指向头结点
InThreading(T); //将以T为根的二叉树进行中序线索化
pre->rchild=Thrt; //pre为最右结点**,将pre的右线索指向头结点
pre->RTag=1;
Thrt->rchild=pre; //头结点的右线索指向pre
}
}
遍历中序线索二叉树
void InOrderTraverse_Thr(BiThrTree T)
{//T指向头结点,头结点的左链lchild指向根节点
p=T->lchild; //p指向根结点
while(p!=T) //空树或遍历结束时,p==T
{
while(p->LTag==0) p=p->lchild; //沿左孩子向下
cout<<p->data; //访问左子树为空的结点
while(p->RTag==1&&p->rchild!=T)
{
p=p->rchild;cout<<p->data; //沿右线索访问后继结点
}
p=p->rchild; //转向p的右子树
}
}
练习
先序遍历结果如下,画出对应的二叉树
LTag | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 1 |
---|---|---|---|---|---|---|---|---|---|---|
data | A | G | E | I | D | J | H | C | F | B |
RTag | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 1 |
0:孩子,1:线索,先序:DLR
画出的二叉树如下