1.线索二叉树基本概念

  • 二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历。用二叉树作为存储结构时,取到一个节点,只能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继。
  • 为了保存这种在遍历中需要的信息,我们利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息,n个节点的二叉树中含有n+1个空指针域。
  • 试做如下规定:
    • 若结点有左子树,则其lchild域指示其左孩子,否则令lchild域指示其前驱;
    • 若结点有右子树,则其rchild指示其右孩子,否则令rchild域指示其后继。
    • 为避免混淆,尚需改变结点结构,增加两个标志域LTag和RTag。
  • 其中:
    • LTag=0时,lchild域指示结点的左孩子;LTag=1时,lchild域指示结点的前驱。
    • RTag=0时,rchild域指示结点的右孩子;RTag=1时,rchild域指示结点的后继。

2.二叉树的二叉线索类型定义

typedef struct BiThrNode
{TelemTpye data;struct BiThrNode *lchild,*rchild;      /*左右孩子指针*/int LTag,RTag;               /*左右标志*/
}BiThrNode,*BiThrTree;
  • 以这种结点结构构成的二叉链表作为二叉树的存储结构,叫做线索链表。
  • 指向结点前驱和后继的指针叫做线索
  • 加上线索的二叉树称之为线索二叉树
  • 对二叉树以某种次序遍历使其变成线索二叉树的过程叫做线索化。
  • 由于线索二叉树构造的实质是将二又链表中的空指针改为指向前驱或后继的线索,而前驱或后继的信息只有在遍历时才能得到,因此线索化的过程即为在遍历的过程中修改空指针的过程,可用递归算法。
  • 根据线索的性质的不同,线索二叉树分为:先序线索二叉树中序线索二叉树后序线索二叉树

3.中序线索二叉树

  • 画出以下二叉树对应的中序线索二叉树。
  • 该二叉树中序遍历结果为:  H, D, I, B, E, A, F, C, G

  • 画出与二叉树对应的中序线索二叉树

  • 因为中序遍历序列是:55 40 25 60 28  08 33 54 对应线索树应当按此规律连线,即在原二叉树中添加虚线。

3.1 以结点p为根的子树中序线索化

  • 算法步骤

    • ①如果p非空,左子树递归线索化。
    • ②如果p的左孩子为空,则给p加上左线索,将其LTag置为1,让p的左孩子指针指向pre前驱);否则将p的LTag置为0。
    • ③如果pre的右孩子为空,则给pre加上右线索,将其RIag置为1,让pre的右孩子指针指向p(后继);否则将pre的RTag置为0。
    • ④将pre指向刚访问过的结点p,即pre=p
    • ⑤右子树递归线索化
  • 算法描述
void InThreading(BiThrTree p)
{//pre是全局变量,初始化时其右孩子指针为空,便于在树的最左点开始建线索if(p){InThreading(p->lchild);       // 左子树递归线索化if(!p->lchild){                     // p的左孩子为空p->LTag=1;           // 给p加上左线索p->lchild=pre;        // p的左孩子指针指向pre(前驱)} elsep->LTag=0;if(!pre->rchild){                        // pre的右孩子为空pre->RTag=1;         // 给pre加上右线索pre->rchild=p;       // pre的右孩子指针指向p(后继)elsepre->RTag=0;pre=p;         //保持pre指向p的前驱InThreading(p->rchild);    //右子树递归线索化}
}

3.2 带头结点的二叉树中序线索化

  • 算法描述
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}
}

3.3 遍历中序线索二叉树​​​​​​​

  • 算法步骤

    • ①指针p指向根结点。
    • ②p为非空树或遍历未结束时,循环执行以下操作
      • 沿左孩子向下,到达最左下结点*p,它是中序的第一个结点;
      • 访问*p
      • 沿右线索反复查找当前结点*p的后继结点并访问后继结点,直至右线索为0或者遍历结束;
      • 转向p的右子树。
void InOrderTraverse_Thr(BiThrTree T)
{ // 中序遍历二叉线索树T的非递归算法,对每个数据元素直接输出BiThrTree p;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;}
}                   

4.代码实现

  • main.cpp
#include<iostream>
using namespace std;// 二叉树的二叉线索类型存储表示
typedef struct BiThrNode
{char data; // 结点数据域struct BiThrNode *lchild, *rchild;  // 左右孩子指针int LTag, RTag;
}BiThrNode, *BiThrTree;//全局变量pre
BiThrNode *pre = new BiThrNode;// 建立二叉链表
void CreateBiTree(BiThrTree &T)
{//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树Tchar ch;cin >> ch;if (ch == '#')  T = NULL;  // 递归结束,建空树else{T = new BiThrNode;T->data = ch;           // 生成根结点CreateBiTree(T->lchild); // 递归创建左子树CreateBiTree(T->rchild); // 递归创建右子树}
}                                   // 以结点P为根的子树中序线索化
void InThreading(BiThrTree p)
{// pre是全局变量,初始化时其右孩子指针为空,便于在树的最左点开始建线索if (p){InThreading(p->lchild);   // 左子树递归线索化if (!p->lchild){                      // p的左孩子为空p->LTag = 1;        // 给p加上左线索p->lchild = pre;   // p的左孩子指针指向pre(前驱)}elsep->LTag = 0;if (!pre->rchild){                    // pre的右孩子为空pre->RTag = 1;     // 给pre加上右线索pre->rchild = p;  // pre的右孩子指针指向p(后继)}elsepre->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的非递归算法,对每个数据元素直接输出BiThrTree p;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;}
}                                                   int main()
{pre->RTag = 1;pre->rchild = NULL;BiThrTree tree, Thrt;cout << "请输入建立二叉链表的序列:\n";CreateBiTree(tree);InOrderThreading(Thrt, tree);cout << "中序遍历线索二叉树的结果为:\n";InOrderTraverse_Thr(Thrt);cout << endl;system("pause");return 0;
}
  • 运行结果

​​​​​​​

数据结构—二叉树线索化(线索化的先序、中序、后序遍历)相关推荐

  1. 二叉树前、中、后线索化及对应前、中、后序线索化遍历

    二叉树前中后线索化及对应前中后序线索化遍历(图解) 二叉树线索化都是套路,会一种另外两种只是稍微修改一下代码 值得一提的是后序线索化输出,逆序思维将后序线索化看成前序,采用"前序线索化输出& ...

  2. java中二叉树_Java工程师面试1000题224-递归非递归实现二叉树前、中、后序遍历...

    224.使用递归和非递归实现二叉树的前.中.后序遍历 使用递归来实现二叉树的前.中.后序遍历比较简单,直接给出代码,我们重点讨论非递归的实现. class Node { public int valu ...

  3. 先序序列和后序序列并不能唯一确定二叉树

    数据结构的基础知识中重要的一点就是能否根据两种不同遍历序列的组合(有三种:先序+中序,先序+后序,中序+后序),唯一的确定一棵二叉树.然后就是根据二叉树的不同遍历序列(先序.中序.后序),重构二叉树. ...

  4. 非递归先、中、后序遍历二叉树(C语言)

    文章目录 前言 一.二叉树非递归遍历算法 1.先序遍历 2.中序遍历 3.后序遍历 二.完整程序 三.运行结果实例 前言 本程序采用C语言编写,栈和二叉树的基本操作函数基于严蔚敏老师的<数据结构 ...

  5. 已知一棵二叉树的中序序列和后序序列,写一个建立该二叉树的二叉链表存储结构的算法...

    已知一棵二叉树的中序序列和后序序列,写一个建立该二叉树的二叉链表存储结构的算法 #define N 10 //二叉树节点的个数 char postorderstr[]={};//后序序列 char i ...

  6. 7-10 先序序列创建二叉树,输出先序序列、中序序列、后序序列并输出叶子结点数 (10 分)

    7-10 先序序列创建二叉树,输出先序序列.中序序列.后序序列并输出叶子结点数 (10 分) 对于给定的二叉树,输出其先序序列.中序序列.后序序列并输出叶子结点数. 输入格式: 二叉树的先序遍历序列. ...

  7. 二叉树的构造(前序+中序)---(后序 + 中序)

    二叉树的构造(前序+中序)-(后序 + 中序) 思路:要对前序+中序(后序+中序)的构建树的动态过程要了解,思路比较简单,在了解了这个过程之后,理解下面代码就容易了. 过程 参考图: 前序 + 中序: ...

  8. 二叉树的前、中、后序遍历

    所谓二叉树遍历是按某种特定规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次.访问结点所做的操作依赖于具体的应用问题. 遍历是二叉树上最重要的运算之一,也是二叉树进行其它运算的基础. 二 ...

  9. 二叉树遍历方法——前、中、后序遍历(图解)

    目录 一.前序遍历 (1)递归版本 (2)非递归版本 二.中序遍历 (1)递归版本 (2)非递归版本 三.后序遍历 (1)递归版本 (2)非递归版本 四.总结 五.测试程序 六.程序输出 二叉树的遍历 ...

  10. 满二叉树先序序列转后序序列

    算法一 //利用先序序列和后序序列的关系直接转 void PreToPost(ElemType pre[], int l1, int h1, ElemType post[], int l2, int ...

最新文章

  1. 奇异值分解SVD和偏最小二乘奇异值分解PLSSVD
  2. C# 转换人民币大小金额(WinForm、Asp.Net)
  3. HTML特殊字符编码对照表
  4. 微软自拍:让黑科技拯救不会拍照的你
  5. 【Python数据分析】四级成绩分布 -matplotlib,xlrd 应用
  6. Coding Interview Guide -- 数组的partition调整
  7. 创建vue-cli项目
  8. EXCHANGE 2010 DAG 实验总结
  9. SpringMVC自定义注入controller变量
  10. linux read phy reg,请问如后配置嵌入式网卡LAN91C11X系列的自动协商模式(Auto-Negotiation)?...
  11. Spring 整合Quartz 2实现定时任务五:集群、分布式架构实现探讨
  12. python迷你停车场管理系统_python实现停车管理系统
  13. iOS运行出现No application was specified.
  14. 跨页面实现多选(转)
  15. au计算机内录音乐,win10 audition怎么内录_win10 audition如何录制声音
  16. 删除无法读取源文件或磁盘的文件 删除系统找不到指定路径的文件
  17. [篇三章一]_微软虚拟机 Hyper-V 上安装纯 MS-DOS 6.22 系统
  18. 利用ptython中的tutle画了一个表情包——2020冲冲冲!!
  19. WebServer项目的亮点和难点
  20. ReactNative 刘海屏适配iPhoneX

热门文章

  1. 微信小程序引用外部字体
  2. 第一次登上CSDN的博客
  3. React 系列 - 前言
  4. 论EI、SCI和ISTP检索论文的收录号和期刊号查询方法
  5. 完美世界发布2020业绩预告:游戏净利润预增20%
  6. long long整型
  7. Flink的非Barrier对齐可以优化高反压
  8. CTFShow re2 (RC4
  9. 情侣一起看同步看电影H5网站 电影同步观看平台 (自己写的 已开源)
  10. Springboot 集成 Activiti时启动报错!'org.activiti.spring.boot.SecurityAutoConfiguration