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

embedded/2024/11/17 14:22:28/

一、线索二叉树的产生

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

在有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.ppmy.cn/embedded/138274.html

相关文章

深度学习在边缘检测中的应用及代码分析

摘要: 本文深入探讨了深度学习在边缘检测领域的应用。首先介绍了边缘检测的基本概念和传统方法的局限性,然后详细阐述了基于深度学习的边缘检测模型,包括其网络结构、训练方法和优势。文中分析了不同的深度学习架构在边缘检测中的性能表现&am…

ESP32C3单片机使用笔记---烧录MicroPython

使用MicroPython在ESP32C3单片机上编程,首先需要将MicroPython运行环境烧录到ESP32C3的Flash中去,步骤如下: 1.下载esptool烧录工具,下载地址: https://github.com/espressif/esptool 直接使用git clone git clone…

MongoDB自定义顺序排序

自定义顺序排序方法 以下是在MongoDB中实现自定义顺序排序的方法: 在数据集中添加一个自定义字段。使用update命令或$set操作符为每个文档添加自定义字段。在我们的例子中,我们可以通过以下命令为每个学生添加”grade”字段: db.students.…

androidstudio入门到放弃配置

b站视频讲解传送门 android_studio安装包:https://developer.android.google.cn/studio?hlzh-cn 下载安装 开始创建hello-world 1.删除缓存 文件 下载gradle文件压缩:gradle-8.9用自己创建项目时自动生成的版本即可,不用和我一样 https://…

<websocket><PLC>使用js和html实现webscoket,与PLC进行socket通讯的实例

前言 本文是为了实现从网页端通过websocket与PLC端的socket进行数据通讯。 环境配置 系统:windows 平台:visual studio code 语言:javascript、html、PLC 库:node.js 概述 本文的目的是通过网页端与PLC进行socket通讯,但web端一般并不是直接使用socket,而是websocket,…

高阶数据结构——图

文章目录 目录 文章目录 前言 一、并查集 1、并查集概念 2、并查集的实现 二、图的概念 三、邻接矩阵、邻接表的存储 1、邻接矩阵 写过注释了,就不展开解释了。 2、邻接表 四、图的遍历 1、广度优先遍历 2、深度优先遍历 ​编辑 前言 一、并查集 1、并…

基于微信小程序的在线学习平台+LW示例参考

1.项目介绍 系统角色:管理员、普通用户功能模块:管理员(用户管理、名师管理、视频管理、在线学习管理、论坛交流、试卷管理、试题管理、考试管理等),普通用户(查看相关信息、学习、考试相关等功能&#xf…

开启鸿蒙开发之旅:交互——点击事件

前一节我们写好了”提醒事项“APP首页的静态页面,光有静态页面肯定是不够的,更重要的是交互,今天这一节我将来学习最常用的交互事件——点击事件。 点击事件 说明:组件被点击时触发的事件 作用:监听(感知&a…