线索二叉树

2023-11-05

线索二叉树

线索二叉树的概念:

1.线索:
线索是一种对二叉树的操作,意思是对二叉树进行线索化,其目的是使线索化后的二叉树具有方便被遍历的特点,即不使用递归和栈也可以对线索化之后的树进行中序遍历。
2.基于中序遍历的线索二叉树:
中序遍历,即先遍历节点的左孩子,再遍历节点本身,最后遍历节点的右孩子。
3.前驱与后继:
基于这样的顺序得到的对所有节点的遍历顺序中,在某一节点前一个被遍历的节点称之为该节点的前驱,而在该节点后一个被遍历的节点称之为该节点的后继。
4.线索化节点的标记:
线索二叉树的节点定义有所改变,需要两个用来标记其左右孩子是否被线索化的标记变量:可以称为lisThread和risThread,

  • 如果lisThread的值为1,则表明该节点的左孩子被线索化,指向该节点的前驱节点;如果lisThread的值为0,则表明该节点的左孩子没有被线索化,指向其左孩子本身。
  • 如果risThread的值为1,则表明该节点的右孩子被线索化,指向该节点的后继节点;如果risThread的值为0,则表明该节点的右孩子没有被线索化,指向其右孩子本身。

线索化算法的思路及意义

线索化算法: 我们使用以下算法对一颗二叉树进行线索化,在对一颗二叉树进行中序遍历的过程中,
如果某一节点的左孩子为空,那么将其左孩子指向该节点的前驱,
如果某一节点的右孩子为空,那么再将其右孩子指向该节点的后继。
在这里插入图片描述

线索化二叉树的算法描述起来很简单,但是为什么要这样对树进行线索化,其目的和意义是什么,我们下面进行分析:
首先我们要明确线索二叉树存在的意义,即就是可以在不使用递归和栈的情况下更快地对树进行遍历,这样可以提高算法的效率,也就是说,我们将会使用线索来代替递归的功能,在原本不得不用递归来获得某一结点后继节点的情况下,我们使用线索的功能来解除这样的限制。
那我接下来我们需要分析,在哪些情况下一个节点的后继需要通过递归调用的结束来得到?
首先排除一种可能,如果一个节点有右儿子,那么肯定不需要在递归结束返回时获得它的后继,因为根据中序遍历的顺序,它的后继一定是其右分支上的某一个节点,这完全可以通过不断访问其右分支然后判断每一个节点是否有左儿子来得到。
而如果一个节点没有右儿子,那么说明它的后继不在它的右分支上,我们如果不通过递归和栈的性质将无法获得其后继,这时候我们就可以通过建立线索来确定它的后继节点。
显然当该节点没有右儿子时,我们使用一般的顺序遍历无法获得其后继时,我们就希望将它的空的右儿子加以利用,使其直接指向它的后继节点,这样当我们在进行顺序遍历时,就可以通过该线索直接找到它的后继而避免了使用栈和递归的开销。
那么问题来了,似乎我们只需要有右孩子的线索化就可以完成对树的非递归非栈遍历了,所以左孩子的线索化有什么意义?
关于这个问题,书上似乎没有明确指出,我自己的理解是

  • 首先左孩子的一个用处就是,给定线索化二叉树中的一个节点,我们只要不断地访问它的左孩子,就一定可以得到中序遍历的第一个节点
  • 基于对称的关系,我们不但可以通过不断访问左孩子来得到中序遍历的第一个节点,同样也可以通过访问右孩子来得到中序遍历的最后一个节点,然后我们将遍历的顺序和规则对称变换,就可以通过左孩子的线索化来得到中序遍历的逆序顺序。

线索化二叉树的代码实现

#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode
{
	char data;
	struct TreeNode * left;
	struct TreeNode * right;
	int LisThread;
	int RisThread; 
}*BiTree;
BiTree pre=NULL;//声明全局变量,表示在中序遍历过程中当前节点的前驱 
void CreatTree(BiTree *t)
{
	char data;
	scanf("%c",&data);
	getchar();
	if(data=='0')
	{
		*t=NULL;
		return;
	}
	else 
	{
	*t=malloc(sizeof(struct TreeNode));
	(*t)->data=data;
	printf("请输入左节点:\n");
	CreatTree(&(*t)->left);
	printf("请输入右节点:\n");
	CreatTree(&(*t)->right);
    }
}

void InThreading(BiTree t)//对二叉树进行中序线索化 
{
    if(t==NULL)  return;
    InThreading(t->left);//对左孩子进行线索化 
    
	if(t->left==NULL)
	{
		t->LisThread=1;
		t->left=pre;
	 } 
	if(pre!=NULL&&pre->right==NULL)
	{
		pre->RisThread=1;
		pre->right=t;
	}
	pre=t;
	
	InThreading(t->right);	//对右孩子进行线索化 
}

void InOrderThreading(BiTree t)//中序遍历线索化二叉树 
{
	while(t!=NULL)
	{
		while(!t->LisThread)
		{
			t=t->left;
		}
		printf("%c ",t->data);
		while(t->RisThread)
		{
			t=t->right;
			printf("%c ",t->data);
		}
	    t=t->right;
	}
}
main()
{
 BiTree t=NULL;
 CreatTree(&t);
 InThreading(t);
 InOrderThreading(t);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

线索二叉树 的相关文章

随机推荐

  • 第一篇 Spring Cloud Alibaba入门

    1 为什么会出现Spring Cloud Alibaba 1 1Spring Cloud Netflix项目进入维护模式 官网说明地址 https spring io blog 2018 12 12 spring cloud greenwi
  • 目标检测任务简述

    目标检测竟然也可以说是一个比较上游的任务了 以此为基础的下游任务可以是环境感知 自动驾驶 人体关键点检测等 与图像分类的区别 目标检测物体数量不固定 位置不固定 大小不固定 分类一般都是一张图片中是一个物体 位置在正中间 大小占整张图片的大
  • 腾讯云服务器opencloudos8.6 安装 redis

    下载 先检查安装redis的gcc环境有没有 说明gcc已经自己就装有了 下面是安装gcc 的指令 除了这个之外 也可以使用 gcc安装 yum y install gcc automake autoconf libtool make 自动
  • c++11 std::lock函数模板总结

    一 std lock概念 可以一次锁住两个或者两个以上的互斥量 最少锁两个 优点 它不存在这种因为多个线程中因为锁的顺序问题导致死锁的风险问题 std lock 不会存在死锁的原因 比如std lock g i mutex g j mute
  • STL ---- list 使用

    目录 初始化 追加和删除 迭代器 常用的常量 插入数据 删除数据 其他函数 初始化 使用assign函数初始化 l num assign 3 5 l data assign 1 2 3 4 或者定义的时候就初始化 list
  • sqlilab学习打卡

    less 46 order by 如题 显然这一类题目的注入点在order by处 分别测试了sort 1 2 3 4 发现有回显有报错信息 不过这一关回显的内容不是可以被利用的地方 因此只能使用报错注入 盲注 因为之前从来没有接触过这类
  • Unity3D中的Coroutine详解

    本文太乱 推荐frankjfwang的 全面解析Coroutine技术 Unity中的coroutine是通过yield expression 来实现的 官方脚本中到处会看到这样的代码 疑问 yield是什么 Coroutine是什么 un
  • ESXI 中的虚拟机导出到本地

    ovftool exe工具 在windows如已经安装vmware workstation 在安装目录下有个OVFTool目录直接可使用 例如 C Program Files x86 VMware VMware Workstation OV
  • circos - Session 2 - Lesson 2 - Histograms

    create data track draw a histogram which is a plot type track Two kinds of data tracks plots and links create an image w
  • c/c++游戏逆向驱动开发,游戏辅助保护盾

    功能介绍 1 降低游戏权限 提升游戏权限 禁止游戏后台截图 2 保护进程 隐藏进程 进程内存不被读取 如图 部分功能展示 程序降权 NTSTATUS ChangeHandleAccessState ULONG ulProcessId ULO
  • C++,对于数据结构相同但数据处理方式不同的两种类,可以用虚函数列表地址进行区分和相互转化。

    举个简单的例子 一个数据可能是整型的 也可能是浮点数 在运行过程中 类型有可能发生变化 如果统一用浮点数表示 那么整型的取值范围就会变小 如果要兼顾整型的取值范围 一般来说 就得使用更多的空间来表示浮点数或者数的类型 今天突发奇想 直接用虚
  • 思维导图在Ubuntu下的安装与使用

    FreeMind是一款跨平台的 基于GPL协议的自由软件 用Java编写 是一个用来绘制思维导图的软件 其产生的文件格式后缀为 mm 可用来做笔记 脑图记录 脑力激汤等 Ubuntu下只需要在终端输入 sudo apt get instal
  • 设置docker容器镜像加速器(阿里云)

    为了加速Docker容器的拉取 我们可以设置Docker容器镜像加速器 以阿里云镜像加速器为例 您可以按照以下步骤进行设置 1 登录阿里云容器镜像服务 登录阿里云容器镜像服务 注册账号并登录 进入容器镜像服务管理控制台 2 获取镜像加速器地
  • 吃透Chisel语言.09.Chisel项目构建、运行和测试(一)——用sbt构建Chisel项目并运行

    Chisel项目构建 运行和测试 一 用sbt构建Chisel项目并运行 上一大部分介绍了Chisel的基础语法 但除了教程开始的Demo以外 我们还没有开始写Chisel代码 这对于学习编程语言来说是大忌 不过好在Chisel基础语法部分
  • 使用微 PE(U盘)安装 Windows 10 操作系统

    1 下载微PE安装包 官方下载链接 http www wepe com cn download html现在官方需要乐捐才能下载 有条件的同学可以适当的支持一下作者 2 制作PE启动盘 软件下载完成后 就可以开始制作WinPE了 需要注意的
  • 谁在成为产业经济发展的推车人?

    区域发展的新蓝图中 京东云能做什么 它的角色是什么 这个问题背后 隐藏的不仅是京东云自身的能力和价值 更是其作为中国互联网云厂商的代表之一 对 技术 产业 的新论证 作者 皮爷 出品 产业家 关于云厂商 外界更多的认知是在技术和产品层面 不
  • Vulkan Windows VS2022 开发环境配置

    1 确保编译器支持C 17 所以需要Visual Studio 2017及其以上版本 我这里用的是2022 确保环境安装了CMake CMake gui 可选装 2 下载Vulkan SDK 到 https vulkan lunarg co
  • Open3d读写pcd点云文件

    本文为博主原创文章 未经博主允许不得转载 本文为专栏 python三维点云从基础到深度学习 系列文章 地址为 https blog csdn net suiyingy article details 124017716 1 Open3d 安
  • 计算机ip 地址异常,电脑显示IP地址错误怎么办

    有用户和小编反映 电脑无法上网 经过诊断后显示是IP地址错误的原因 如果我们遇到了这样的错误应该怎么办 所以 在下面的内容中 小编要和大家介绍在电脑提示IP地址错误无法上网的具体解决方法 win8 1 14 首先确定是否禁用了本地连接 如果
  • 线索二叉树

    线索二叉树 线索二叉树的概念 1 线索 线索是一种对二叉树的操作 意思是对二叉树进行线索化 其目的是使线索化后的二叉树具有方便被遍历的特点 即不使用递归和栈也可以对线索化之后的树进行中序遍历 2 基于中序遍历的线索二叉树 中序遍历 即先遍历