二叉树+线索二叉树的一些代码

二叉树(有关遍历补充+代码)

补充

先序遍历和中序遍历有一些小诀窍
先序遍历:这样子一画就可以找到先序遍历为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)
  • 线索二叉树:二叉树加上线索(指向结点的前驱或者后继的指针)
  • 对二叉树以某种遍历使其变成线索二叉树的过程叫做线索化

构造线索二叉树的过程解析

线索化过程就是在遍历过程中修改空指针(将空指针指向前驱或后继)的过程。

线索化二叉树的约定
  1. 头结点:
    LTag=0,lchild指向根
    RTag=1,rchild指向最后一点
  2. 序列第一点若左为空 LTag=1,lchild->头结点
  3. 序列最后一点若右为空 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的右子树
    }
}

练习

先序遍历结果如下,画出对应的二叉树

LTag0011110101
dataAGEIDJHCFB
RTag0001010111

0:孩子,1:线索,先序:DLR
画出的二叉树如下
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值