【数据结构】10.线索二叉树

一、线索二叉树的产生

采用先序、中序、后序三种方法遍历二叉树后都可以得到一个线性序列,序列上的每一个结点(除了第一个和最后一个)都有一个前驱和一个后继,但是,这个线性序列只是逻辑的概念,不是物理结构。
在这里插入图片描述
二叉链体现的是父子关系,不一定是结点在遍历序列中的前驱和后继。

在有n个结点的二叉链表中,有n+1个空指针 。那么能否利用这些空指针来存放前驱和后继结点的地址呢?然后可以像遍历链表一样方便的遍历二叉树序列呢?
这也就是线索二叉树产生的背景。线索二叉树可以解决部分的上述问题,加快在序列中查找前驱和后继节点的速度,但同样的也增加了在树中插入和删除节点的难度。

二、二叉树线索化

二叉树线索化是将二叉链表中的空指针改为指向前驱或后继结点。而前驱结点和后继结点只要在遍历时才能拿到,所有二叉树线索化分为先序线索二叉树、中序线索二叉树和后序线索二叉树

如果当前节点没有左子树,那么该节点的左指针指向遍历序列中它的前驱结点。
如果当前节点没有右子树,那么该节点的右指针指向遍历序列中它的后继结点。

在这里插入图片描述

2.1 线索二叉树的定义

typedef int ThreadedBinaryTreeDataType;typedef struct ThreadedBinaryTree
{ThreadedBinaryTreeDataType _data;	struct ThreadedBinaryTree* _left;	struct ThreadedBinaryTree* _right;int _LeftFlag, _RightFlag;	//左右指针类型:0表示非线索指针,1表示线索指针
}TBT,*pTBT;

2.2 先序线索二叉树

在这里插入图片描述
将二叉树进行先序遍历得到的序列就是先序序列,我们需要将他们进行连接。很显然,我们需要找到每一个结点的后继结点。

如果当前结点的右指针存放的是线索,右指针指向的结点即为后续节点。
如果当前结点的右指针存放的是结点,取左子结点,如果左子结点为空,取右子结点。

void _ThreadedPrevOrder(TBT* root)
{if (root == NULL)return;if (root->left == NULL){root->left = prev;root->LeftFlag = 1;}if (prev && prev->right == NULL){prev->right = root;prev->RightFlag = 1;}prev = root;if(root->LeftFlag==0)_ThreadedPrevOrder(root->left);if(root->RightFlag==0)_ThreadedPrevOrder(root->right);
}void ThreadedPrevOrder(TBT* root)
{if (root == NULL)return;_ThreadedPrevOrder(root);prev->right = NULL;prev->RightFlag = 1;
}

2.3 后序线索二叉树

在这里插入图片描述
同样的,将二叉树进行后序遍历得到的序列就是后序序列,我们需要将他们进行连接。很显然,我们需要找到每一个结点的前驱结点。

如果当前结点的左指针存放的是线索,左指针指向的结点即为前驱节点。
如果当前结点的左指针存放的是结点,取右子结点,如果右子结点为空,取左子结点。

void _ThreadedPostOrder(TBT* root)
{if (root == NULL)return;_ThreadedPostOrder(root->left);_ThreadedPostOrder(root->right);if (root->left == NULL){root->left = prev;root->LeftFlag = 1;}if (prev && prev->right == NULL){prev->right = root;prev->RightFlag = 1;}prev = root;
}void ThreadedPostOrder(TBT* root)
{if (root == NULL)return;_ThreadedPostOrder(root);
}

2.4 中序线索二叉树

在这里插入图片描述
将二叉树进行中序遍历得到的序列就是中序序列,我们需要将他们进行连接。很显然,我们需要找到每一个结点的前驱结点和后续结点。

如果当前结点的右指针存放的是线索,右指针指向的结点即为后续节点。
如果当前结点的右指针存放的是结点,右子树中序遍历序列的第一个结点(最左)就是后续节点。
如果当前结点的左指针存放的是线索,左指针指向的结点即为前驱节点。
如果当前结点的左指针存放的是结点,左子树中序遍历序列的最后一个结点(最右)就是后续节点。

void _ThreadedInOrder(TBT* root)
{if (root == NULL)return;_ThreadedInOrder(root->left);if (root->left == NULL){root->left = prev;root->LeftFlag = 1;}if (prev && prev->right == NULL){prev->right = root;prev->RightFlag = 1;}prev = root;_ThreadedInOrder(root->right);
}void ThreadedInOrder(TBT* root)
{if (root == NULL)return;_ThreadedInOrder(root);prev->right = NULL;prev->RightFlag = 1;
}

三、遍历线索二叉树

3.1 遍历中序线索二叉树

void inOrderTraverseThTree(TBT* root)
{//找到初始节点TBT* head = root;while (head->left)head = head->left;while (head){printf("%d ", head->data);//找下一个访问的结点if (head->right && head->RightFlag == 1)head = head->right;else if (head->right){head = head->right;while (head->left && head->LeftFlag == 0)head = head->left;}else if (head->right == NULL)break;}
}

3.2 遍历先序线索二叉树

void PrevOrderTraverseThTree(TBT* root)
{TBT* head = root;while (head){printf("%d ", head->data);if (head->LeftFlag == 0)head = head->left;elsehead = head->right;}
}

3.3 遍历后序线索二叉树

对于后序线索二叉树的遍历是要复杂一点的,对于根节点的后继结点是不好定位的,最好使用到三叉链,当然也可以迭代找到,这里就不演示了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/60879.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何合理设计一套springcloud+springboot项目中的各个微服务模块之间的继承关系的最优方案

文章目录 一、模块化设计所遵循的原则二、项目架构设计三、各个模块作用说明3.1 core 模块3.2 common 模块3.3 generatorcode模块3.4 business 模块3.5 web 模块3.6 admin 模块3.7 父pom 四、采用import引入SpringBoot 在springcloud微服务项目中经常用到多模块化的架构设计&am…

HarmonyOS4+NEXT星河版入门与项目实战--------开发工具与环境准备

文章目录 1、熟悉鸿蒙官网1、打开官网2、下载 DevEco Studio3、HarmonyOS 资源库4、开发指南与API 2、安装 DevEco Studio1、软件安装2、配置开发工具 1、熟悉鸿蒙官网 1、打开官网 百度搜索 鸿蒙开发者官网 点击进入开发者官网,点击开发,可以看到各种…

单元测试、集成测试、系统测试、验收测试、压力测试、性能测试、安全性测试、兼容性测试、回归测试(超详细的分类介绍及教学)

目录 1.单元测试 实现单元测试的方法: 注意事项: 2.集成测试 需注意事项: 实现集成测试的方法: 如何实现高效且可靠的集成测试: 3.系统测试 实现系统测试的方法: 须知注意事项: 4.验收测试 实现验…

Ubuntu24 上安装搜狗输入法

link 首先在终端中依次输入以下代码 sudo apt update sudo apt install fcitx 找到语言支持 在终端中依次输入 sudo cp /usr/share/applications/fcitx.desktop /etc/xdg/autostart/ sudo apt purge ibus 进入网页 搜狗输入法linux-首页​ shurufa.sogou.com/linux 找到刚才下…

FairyGUI和Unity联动(入门篇)

一、FairyGUI编辑器中 1.新建按钮、新建组件 编辑器中界面简易设计如下 2.文件-发布设置-发布路径:自己unity项目Resources所在的路径 二、Unity 使用代码展示UI using FairyGUI; using System.Collections; using System.Collections.Generic; using UnityEngi…

从系统崩溃到绝地反击:一次微服务存储危机的救赎

“怎么会这样?”凌晨两点,我盯着监控面板,心跳加速。用户请求像洪水猛兽般涌来,每一秒都在增加,而服务器却毫无回应。电梯般的访问量突如其来,仿佛一夜之间,我们的微服务系统被压入了崩溃的边缘…

推荐一个基于协程的C++(lua)游戏服务器

1.跨平台 支持win,mac,linux等多个操作系统 2.协程系统 使用汇编实现的上下文模块,C模块实现的协程调度器,使用共享栈,支持开启上千万协程,一个协程大概使用2000字节 3.rpc系统 强大的rpc系统,功能模块可以使用c或…

【Java知识】Java性能测试工具JMeter

一文带你了解什么是JMeter 概述JMeter的主要功能:JMeter的工作原理:JMeter的应用场景:JMeter的组件介绍: 实践说明JMeter实践基本步骤:JMeter实践关键点: JMeter支持哪些参数化技术?常见插件及其…

Redis的缓存穿透、缓存雪崩、缓存击穿问题及有效解决方案

目录 一、缓存穿透 1.简介 2.解决方案 3.修改前的代码 4.修改过后的代码 二、缓存雪崩 1.简介 2.解决方案 三、缓存击穿 1.简介 2.解决方案 3.用代码来实现互斥锁来解决缓存击穿 4.用代码来实现逻辑过期解决缓存击穿 四、缓存穿透和缓存击穿的区别 一、缓存穿透 …

Codeforces Round 987 (Div. 2) ABCD

链接: Codeforces Round 987 (Div. 2) A:Penchick and Modern Monument 大意: 单调非增序列操作多少步变成单调非减 思路: 最后的数一定是相同的,为出现次数最多的那个数,结果就是n减去出现次数最多的数 代码&…

CPU的性能指标总结(学习笔记)

CPU 性能指标 我们先来回顾下,描述 CPU 的性能指标都有哪些。 首先,最容易想到的应该是 CPU 使用率,这也是实际环境中最常见的一个性能指标。 用户 CPU 使用率,包括用户态 CPU 使用率(user)和低优先级用…

深度学习反向传播需要可导还是需要可微

针对这个问题, 我们先说结论, 在深度学习中,反向传播需要可导性,而不是严格的可微分性。这是因为反向传播的核心是计算损失函数相对于模型参数的导数(梯度),以便通过梯度下降法进行参数更新。 …

【go从零单排】Environment Variables环境变量

🌈Don’t worry , just coding! 内耗与overthinking只会削弱你的精力,虚度你的光阴,每天迈出一小步,回头时发现已经走了很远。 📗概念 在 Go 语言中,环境变量是用于配置程序行为的一种常见方式。它们可以用…

信捷PLC转以太网连接电脑方法

信捷XC/XD/XL等系列PLC如何上下载程序?可以选择用捷米特JM-ETH-XJ模块轻松搞定,并不需要编程,即插即用,具体看见以下介绍: 产品介绍 捷米特JM-ETH-XJ是专门为信捷PLC转以太网通讯面设计,可实现工厂设备信息化需求,对…

面试篇-项目管理

⼀、构建管理 项目为什么选择Maven构建? 选择Maven进行项目构建有以下几个主要原因: 1. 依赖管理:Maven 提供了强大的依赖管理功能,可以自动下载项目所需的第三方库和依赖,并且可以管理这些依赖的版本、范围等信息。这简化了项…

【golang-技巧】-线上死锁问题排查-by pprof

1.背景 由于目前项目使用 cgo golang 本地不能debug, 发生死锁问题,程序运行和期待不一致,通过日志排查可以大概率找到 阻塞范围,但是不能找到具体问题在哪里,同时服务器 通过k8s daemonset 部署没有更好的方式暴露端口 获取ppr…

CentOS7.9 源码编译 FreeSWITCH 1.10.12

建议 CentOS7.9 最小安装&#xff0c;不然容易冲突 #!/bin/bash### 更换 repomkdir /root/repo mv /etc/yum.repos.d/*.repo /root/repocat <<"EOF" > /etc/yum.repos.d/ali.repo [base] nameCentOS-$releasever - Base - mirrors.aliyun.com failovermetho…

AVL树的删除方法简单实现

看过前面的AVL树的介绍和插入方法实现AVL树了解并简单实现-CSDN博客&#xff0c;接着可以来学习删除方法的实现 目录 1.AVL树的删除 2.平衡因子调节 3.删除代码逻辑 4.AVL树的整体代码 1.AVL树的删除 因为AVL树也是二叉搜索树&#xff0c;可按照二叉搜索树的方式将节点删除…

ArcGIS的汉字(亚洲文本)垂直标注

01 需求说明 实现ArcGIS的汉字&#xff08;亚洲文本的垂直标注&#xff09;。 启用 Maplex 标注引擎。 在标注 工具条上单击标注管理器按钮 。 选中要进行标注的图层旁边的复选框。 选择图层下方的标注分类。 单击符号。 选中 CJK 字符方向复选框。 仅当字体有垂直的文本度…

C#中 layout的用法

在C#中&#xff0c;layout并不是一个直接用于C#语言本身的关键字或特性。然而&#xff0c;layout在与C#紧密相关的某些上下文中确实有其用途&#xff0c;特别是在涉及用户界面&#xff08;UI&#xff09;设计和数据展示时。以下是几个常见的与layout相关的用法场景&#xff1a;…