【考研】数据结构——线索二叉树

2023-11-18

CSDN话题挑战赛第2期
参赛话题:学习笔记

前言

本文内容源于对《数据结构(C语言版)》(第2版)、王道讲解学习所得心得、笔记整理和总结。

本文针对线索二叉树,在最后的练习中,以举例子说明该排序方法,配以图文,讲解详细(含408真题)。

可搭配以下链接进行学习:

【考研】《数据结构》知识点总结.pdf_考研-其它文档类资源-CSDN下载

【2023考研】数据结构常考应用典型例题(含真题)_住在阳光的心里的博客-CSDN博客

目录

前言

一、基本概念

1、引入线索二叉树的原因

2、线索二叉树的规定

 3、二叉树的二叉线索类型定义

4、中序线索二叉树与对应的中序线索链表

二、构造线索二叉树

1、算法1:以结点 p 为根的子树中序线索化的过程

2、算法2:带头结点的二叉树中序线索化

三、遍历中序线索二叉树

1、算法步骤

2、算法描述

3、算法分析

四、习题


一、基本概念

1、引入线索二叉树的原因

当二叉树以二叉链表作为存储结构时,只能找到结点的左、右孩子信息,而不能直接得到结点在任一序列中的前驱和后继信息,这种信息只有在遍历的动态过程中才能得到,为此引入线索二叉树来保存这些在动态过程中得到的有关前驱和后继的信息

虽可在每个结点中增加两个指针域来存放在遍历时得到的有关前驱和后继信息,但这样做使得结构的存储密度大大降低。由于 n 个结点的二叉链表中必定存在 n + 1个空链域( 2n 个指针域,因此可以充分利用这些空链域来存放结点的前驱和后继信息

2、线索二叉树的规定

若结点有左子树,则其 lchild 域指示其左孩子,否则令 lchild 域指示其前驱;

若结点有右子树,则其 rchild 域指示其右孩子,否则令 rchild 域指示其后继。

为了避免混淆,尚需改变结点结构,增加两个标志域,其结点形式如图1所示。 

 3、二叉树的二叉线索类型定义

//二叉树的二又线索存储表示
typedef struct BiThrNode{
    TElemType data;
    struct BiThrNode *lchild, *rchild;
    int LTag, RTag;
}BiThrNode, *BiThrTree;

以这种结点结构构成的二叉链表作为二叉树的存储结构,叫做线索链表,其中指向结点前驱和后继的指针,叫做线索

加上线索的二叉树称之为线索二叉树(Threaded Binary Tree)。对二又树以某种次序遍历使其变为线索二叉树的过程叫做线索化

4、中序线索二叉树与对应的中序线索链表

实线:指针(指向左、右子树)

虚线:线索(指向前驱和后继)

为方便,仿照线性表的存储结构,在二叉树的线索链表上也添加一个头结点,并令其 lchild 域的指针指向二又树的根结点,其 rchild 域的指针指向中序遍历时访问的最后一个结点;同时,令二叉树中序序列中第一个结点的 lchild 域指针最后一个结点 rchild 域的指针均指向头结点

这好比为二又树建立了一个双向线索链表,既可从第一个结点起顺后继进行遍历,也可从最后一个结点起顺前驱进行遍历。


 

二、构造线索二叉树

由于线索二叉树构造的实质将二叉链表中的空指针改为指向前驱或后继的线索,而前驱或后继的信息只有在遍历时才能得到,因此线索化的过程即为在遍历的过程中修改空指针的过程,可用递归算法。

对二叉树按照不同的遍历次序进行线索化,可以得到不同的线索二叉树,包括先序线索二叉树、中序线索二叉树和后序线索二叉树。

下面重点介绍中序线索化的算法。

为了记下遍历过程中访问结点的先后关系,附设一个指针 pre 始终指向刚刚访问过的结点,而指针
p 指向当前访问的结点,由此记录下遍历过程中访问结点的先后关系。

1、算法1:以结点 p 为根的子树中序线索化的过程

(1)算法步骤

① 如果 p 非空,左子树递归线索化。
② 如果 p 的左孩子为空,则给 p 加上左线索,将其 LTag 置为1,让 p 的左孩子指针指向前驱;否则将 p 的 LTag 置为0。
③ 如果 pre 的右孩子为空,则给 pre 加上右线索,将其 RTag 置为1,让 pre 的右孩子指针为 p (后继);否则将 pre 的 RTag 置为 0。
④ 将 pre 指向刚访问过的结点 p,即 pre = p。
⑤ 右子树递归线索化。

(2)算法描述

// pre 是全局变量,初始化时其右孩子指针为空,便于在树的最左点开始建线索
vold InThreading(BiThrTree p){
    if(p){
        InThreading(p->lchild);       //左子树递归线索化

        if(!p-> lchild){   // p 的左孩子为空
            p->LTag = l;    //给p加上左线索
            P->lchild = pre;     //p的左孩子指针指向 pre (前驱)
        }
        else{
            p->LTag = 0;
        }

        if(pre->rchild){     //pre 的右孩子为空
            pre->RTag = l;    //给 pre 加上右线索
            pre->rchild = p;    //pre的右孩子指针指向p (后继)
        }
        else{
            p->RTag = 0;
        }

        pre = p;     //保持 pre 指向 p 的前驱
        InThreading(p->rchlld);    //右子树递归线索化
    }
}

2、算法2:带头结点的二叉树中序线索化

通过调用算法1来完成整个二叉树的中序线索化。算法描述如下:

//中序遍历二叉树T,并将其中序线索化,Thrt指向头结点
void InorderThreading(BiThrTree &Thrt, BiThrTree T){
    Thrt-new BiThrNode;      //建头结点

    Thrt->LTag = 0;         //头结点有左孩子,若树非空,则其左孩子为树根
    Thrt->RTag = l;          //头结点的右孩子指针为右线索
    Thrt->rchild = Thrt;         //初始化时右指针指向自己

    if(!T){
        Thrt->lchild = Thrt;        //若树为空,则左指针也指向自己
    }
    else{
        Thrt->lchild = T; 
        pre = Thrt;        //头结点的左孩子指向根,pre初值指向头结点

        InThreading(T);      //调用算法1,对以T为根的二又树进行中序线索化
        pre->rchild = Thrt;        //算法1结束后,pre为最右结点,pre的右线索指向头结点
        pre->RTag = l; 
        Thrt->rchild = pre;    //头结点的右线过指向 pre
    }
}

三、遍历中序线索二叉树

① 查找 p 指针所指结点的前驱:
● 若 p->LTag 为1,则 p 的左链指示其前驱;
● 若 p->LTag 为0,则说明 p 有左子树,结点的前驱是遍历左子树时最后访问的一个结点 ( 左子树中最右下的结点 ) 。

② 查找 p 指针所指结点的后继:
● 若 p->RTag 为1,则 p 的右链指示其后继,以图 2 所示的中序线索树为例来看,结点 b 的后继为结点*;
● 若 p->RTag 为 0,则说明 p 有右子树。根据中序遍历的规律可知,结点的后继应是遍历其右子树时访问的第一个结点,即右子树中最左下的结点。例如,在找结点 * 的后继时,首先沿右指针找到其右子树的根结点-,然后顺其左指针往下直至其左标志为 1 的结点,即为结点 * 的后继,在图中是结点 c 。
 

1、算法步骤

① 指针 p 指向根结点。
② p 为非空树或遍历未结束时,循环执行以下操作:
        ● 沿左孩子向下,到达最左下结点 *p,它是中序的第一个结点;
        ● 访问 *p;
        ● 沿右线索反复查找当前结点 *p 的后继结点并访问它,直至右线索为 0 或者遍历结束;
        ● 转向 p 的右子树。

2、算法描述

// T 指向头结点,头结点的左链 lchild 指向根结点,可参见线索化算法2。
// 中序遍历二又线索树 T 的非递归算法,对每个数据元素直接输出
void InOrderTraverse Thr (BiThrTree T)
{
    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 的右子树
    }
}

3、算法分析

遍历线索二又树的时间复杂度为O(n),空间复杂度为O(1),这是因为线索二叉树的遍历不需要使用栈来实现递归操作。
 

四、习题

1、在二叉树的前序序列、中序序列和后序序列中,所有叶子结点的先后顺序(     B     )

A. 都不相同                                                                 B. 完全相同               

C. 前序和中序相同,而与后序不同                             D. 后序和中序相同,而与前序不同   

解:在三种遍历方式中,访问左右子树的先后顺序是不变的,只是访问根结点的顺序不同,因此叶子结点的先后顺序完全相同。

2、某二叉树的先序序列和后序序列正好相反,则该二叉树一定是(     B     )

A. 空或只有一个结点                                             B. 高度等于其结点数    

C. 任一结点无左孩子                                             D. 任一结点无右孩子   

解:非空的二叉树的先序序列和后序序列相反,即 “根左右” 与 “左右根” 顺序相反,因此树只有根结点,或根结点只有左子树或右子数,以此类推,其子树具有同样的性质,任意结点只有一个孩子,才能满足题目条件,树形应为一个长链。

3、线索二叉树是一种_____物理______结构。

解:二叉树是一种逻辑结构,但线索二叉树是加上线索后的链表结构,即它是二叉树在计算机内部的一种存储结构,即是一种物理结构。

4、n 个结点的线索二叉树上含有的线索数为_____n + 1______。

解:n 个结点共有链域指针 2n 个,其中,除根结点外,每个结点都被一个指针指向。剩余的链域建立线索,共 2n - (n - 1) = n + 1个线索。

5、一棵左子树为空的二叉树进行先序线索化,其中空的链域个数是_____2______。

 解:对左子树为空的二叉树进行先序线索化,根结点的左子树为空,并且也没有前驱结点(先遍历根结点),先序遍历的最后一个元素为叶结点,左、右子树均为空且有前驱无后继结点,所以线索化后,树中空链域有 2 个。

6、【2010统考真题】下列线索二又树中(用虚线表示线索)符合后序线索树定义的是(  D  )

解:题中所给二叉树的后序序列为 dbca, 结点 d 无前驱和左子树,左链域空,无右子树,右链域指向其后继结点 b;结点 b 无左子树,左链域指向其前驱结点 d;结点 c 无左子树,左链域指向其前驱结点 b,无右子树,右链域指向其后继结点 a。正确选项为D。
 

7、二叉树在线索化后,仍不能有效求解的问题是(    D   )。
A. 先序线索二叉树中求先序后继              B. 中序线索二叉树中求中序后继
C. 中序线索二叉树中求中序前驱              D. 后序线索二叉树中求后序后继

解: 后序线索二叉树不能有效解决求后序后继的问题。如下图所示,结点 E 的右指针指向右孩子,而在后序序列中E的后继结点为 B,在查找 E 的后继时后序线索不能起到任何作用,只能按常规方法来。

8、若 X 是二叉中序线索树中一个有左孩子的结点,且 X 不为根,则 X 的前驱为(    C    )。
A. X 的双亲                                             B. X 的右子树中最左的结点
C. X 的左子树中最右结点                       D. X 的左子树中最右叶结点

 解:在二叉中序线索树中,某结点若有左孩子,则按照中序 “左根右” 的顺序,该结点的前驱结点为左子树中最右的一个结点(注意,并不一定是最右叶子结点)。

9、(  C  )的遍历仍需要栈的支持。
A. 前序线索树             B. 中序线索树               C. 后序线索树               D. 所有线索树

解:后序线索树遍历时,最后访问根结点,若从右孩子 x 返回访问父结点,则由于结点 x 的右孩子不一定为空 (右指针无法指向其后继),因此通过指针可能无法遍历整棵树。

如下图所示,结点中的数字表示遍历的顺序,图(c) 中结点 6 的右指针指向其右孩子 5,而不指向其后序后继结点 7,因此后序遍历还需要栈的支持,而图 (a) 和图 (b) 均可遍历。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【考研】数据结构——线索二叉树 的相关文章

  • 解决redis-server.exe不是内部或外部命令

    报错 redis server exe不是内部或外部命令 原因 未进入到redis的安装目录下 解决 先找到redis安装路径 复制之后 在终端中输入cd xxxxx redis的安装路径 进入安装目录之后再次输入redis server
  • 深入学习jquery源码之data()

    深入学习jquery源码之data jQuery data element key value 概述 在元素上存放数据 返回jQuery对象 注意 这是一个底层方法 你应当使用 data 来代替 此方法在jQuery 1 8中删除 但你仍然
  • Java面向对象编程

    将N条长度均为M的有序链表进行合并 合并以后的链表也保持有序 时间复杂度为 A O N M logN B O N M C O N D O M 答案 A 下设栈S的初始状态为空 元素a b c d e f依次入栈S 出栈的序列为b d c f
  • 百度网盘登陆验证提示:无法访问此页面,或者二维码显示失败,弹窗显示:无法访问此页面,确保web地址。。。。

    百度网盘登陆验证提示 无法访问此页面 或者二维码显示失败 弹窗显示 无法访问此页面 确保web地址 遇到百度网盘登陆时显示下面的情况 原因 是自己电脑的IE浏览器设置出了问题 没有显示出来应有的验证界面 解决方案 打开电脑的IE浏览器 在右
  • Apex安装失败(笔记记录分享)

    Apex安装失败 笔记记录 1 错误合集 No 1 error detected in the compilation of csrc multi tensor scale kernel cu No 2 module torch nn ha
  • Java long Long

    转载 https www cnblogs com c2g5201314 p 13024261 html 1 long 是 基本类型 Long 是 对象类型 2 long 默认值是 0 Long 默认值是 null 3 比较方法 1 Long
  • LVS 就是这么简单(数字后端物理验证篇)

    LVS 就是这么简单 数字后端物理验证篇 文章右侧广告为官方硬广告 与吾爱IC社区无关 用户勿点 点击进去后出现任何损失与社区无关 今天吾爱 IC 社区小编为大家带来数字 IC 后端实现物理验证中关于 LVS 的主题分享 其实小编一直觉得这

随机推荐

  • 调整echarts中图与legend的距离

    1 正常调整legend的位置 通过X改变横坐标位置 通过Y改变纵轴位置 x 可设定图例在左 右 居中 y 可设定图例在上 下 居中 legend y bottom data 阳性转阴性 阴性转阳性 阳性无症状转有症状 未检测 2 如果觉得
  • STM32F103ZET6【标准库函数开发】------04 串口USART1控制LED

    一 硬件介绍 STM32F103ZET6有5个串口 查看引脚图可以找到对应的IO口分别如下 串口 USART1 USART2 USART3 UART4 UART5 输入 输出方式 USARTx TX PA9 PA2 PB10 PC10 PC
  • forcats

    引子 最近在整理forcats工具包中的函数 发现该包只有fct reorder2 函数的功能不太容易理解 所以单独写一篇推文来介绍它 根据上篇提到的函数分类 它可以归为 调整类别顺序的函数 与它类似的还有一个fct reorder 函数
  • 九龙战登录只显示一个服务器,九龙战登录失败进不去解决办法

    九龙战是腾讯推出的一款三国题材的动作竞技手游 目前已经开启了不删档测试 但是玩家们在游戏中遇到了登录失败进不去的情况 下面小编就为大家介绍一下九龙战登录失败进不去解决办法 首先玩家们要知道九龙战是一款不删档测试不久的游戏 所以在这期间出现什
  • Android基于BroadcastReceiver和Service、SoundPool开发的防过充助手app

    前段时间换了一个小米4C手机 可是发现它的充电充满没有提醒 上一个手机换了就是因为不爱惜电池 让它过充的次数多了 虽然听别人说小米4c手机充电器是智能充电器 有保护作用 但我自己还是不放心 于是就亲手写了一个防过充小应用 已经在使用 可以达
  • 如何使用LaTeX制作PPT?

    作为LaTeX排版软件 LaTeX主要被用来制作书籍和文章 但由于现代LaTeX系统主要以PDF文件为输出方式 授课 演讲用的计算机幻灯片也日益成为LaTeX的一个重要应用 LaTeX中专门用来制作幻灯片的工具有powerdot文档类 pr
  • 探索.NET:​构建现代软件开发的核心框架

    摘要 在现代软件开发领域 选择一个合适的开发框架对于成功构建可靠 高效的应用程序至关重要 NET 读作 dot net 是一个强大而广泛使用的框架 为开发人员提供了丰富的工具和功能 以简化开发过程并加快交付时间 本文将介绍 NET的基本概念
  • 【手撕RPC服务分几步】

    手撕RPC服务分几步 前言 什么是RPC 从被调用方 provider 来说 从调用方 consumer 来说 扩展思考 dubbo架构图 前言 本文试图通过手撕RPC的理论步骤来帮助我们更好的理解其特性 也更好的理解像Dubbo sofa
  • flutter 填坑之旅(dart学习笔记篇)

    俗话说 工欲善其事必先利其器 想要撸flutter app 而不懂 dart 那就像一个不会英语的人在和英国人交流 懵 安装 dart 就不用说了 比较简单dart 官网 https dart dev 安装完成后就开启学习dart 旅程吧
  • MyEclipse配置Tomcat7

    首先我们打开Myeclipse 进入偏好设置window gt perferences 进入偏好设置 perferences 在偏好设置的搜索栏那里输入tomcat查找tomcat 如下图所示 3 我们可以看到搜索到的有四个tomcat项
  • (笔试前准备)字符串匹配算法总结

    我想说一句 我日 我讨厌KMP KMP虽然经典 但是理解起来极其复杂 好不容易理解好了 便起码来巨麻烦 老子就是今天图书馆在写了几个小时才勉强写了一个有bug的 效率不高的KMP 特别是计算next数组的部分 其实 比KMP算法速度快的算法
  • STM32 HAL库更改中断向量表的偏移地址

    以STM32F767为例 打开system stm32f7xx c文件 定位VECT TAB OFFSET 更改此宏定义的值 即可更改偏移量
  • 富维火焰识别算法

    火灾是威胁公共安全 危害人民生命财产的灾害之一 加强消防安全管理是头等大事 对火灾做到早预防 早发现 尽量避免火灾的发生尤为重要 近年来随着网络摄像机的广泛使用以及图像处理技术的不断发展 基于视频的北京富维图像火焰识别算法得到了越来越多的关
  • Android Rom修改制作工具软件集合

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 1 SIN2IMG 用于固件ftf中system sin的解包 下载地址 SIN2IMG rar 使用方法 将固件ftf文件用rar打开 解压出system sin文件 将
  • Idea 修改默认的Maven配置及修改为阿里源

    每次使用Idea创建或者导入Maven项目的时候 Idea都会使用系统默认的Maven 此时 如果我们想使用自定义安装的Maven 需要在File gt other settings gt Settings for New Projects
  • STM32-custom usb

    如何建立一个自定义的HID工程呢 下面就来讲讲 首先先介绍下工程的架构 工程的总体架构下图所示 按照下图架构建工程 分析下工程布局 首先是APP 这个组里存放着主文件mian c 管理所有中断服务程序stm3210x it c 及其管理外设
  • PageObjects支持库-Poium使用方法

    PO模式 学过自动化的都知道PageObjects模式 将页面对象封装为类 页面元素和操作封装为类的属性和方法 在测试方法中调用页面对象进行测试 关于PO模式可见 http t csdn cn 0DBlP 在PO模式下 我们一般定义个一个基
  • 想写一本书,而这是序言

    口袋书 序言 现在的风口是什么 很多人会答人工智能 Artificial Intelligence AI 人工智能是一项伟大的发明 我们不得不承认 它已经为社会带来了翻天覆地的变化 并 将在未来卷起更大的风暴 不了解人工智能 就难以在这个
  • 前端js将扁平化数据转化为=菜单树

    let menuList id 1 pid 1 name 江西 id 2 pid 1 name 南昌 id 3 pid 1 name 九江 id 4 pid 1 name 广东 id 5 pid 4 n
  • 【考研】数据结构——线索二叉树

    CSDN话题挑战赛第2期 参赛话题 学习笔记 前言 本文内容源于对 数据结构 C语言版 第2版 王道讲解学习所得心得 笔记整理和总结 本文针对线索二叉树 在最后的练习中 以举例子说明该排序方法 配以图文 讲解详细 含408真题 可搭配以下链