线索二叉树结构
线索二叉树结构
- 1.线索二插树的作用
- 2.线索二叉树的定义
- 3.线索二叉树的结构
- 4. 线索二叉树的操作
- 4.1. 建立一棵中序线索二叉树
- 4.2. 在中序线索二叉树上查找任意结点的中序前驱结点
- 4.3. 在中序线索二叉树上查找任意结点的中序后继结点
- 4.4. 在中序线索二叉树上查找任意结点在先序下的后继结点
- 4.5. 在中序线索二叉树上查找任意结点在后序下的前驱结点
- 4.6. 在中序线索二叉树上查找值为x的结点
- 4.7. 中序线索二叉树上的插入与删除
- 5. 基于中序线索二叉树的遍历算法
1.线索二插树的作用
通过递归算法或者是用栈与队列实现非递归算法都会有额外空间上的开销。利用n个结点有n+1个空指针域来存放线索,然后利用这个线索来实现不用空额外空间来遍历二叉树。
2.线索二叉树的定义
在某种顺序遍历二叉树的时候,存在直接前驱结点和后继结点的信息,对于非空指针域指向原本的左右孩子,而对于非空指针域来说,左孩子指针指向遍历序列的直接前驱结点,右孩子指向遍历序列的直接后继结点。
这种指针称为线索,加了线索的二叉树称为线索二叉树。
3.线索二叉树的结构
为每个结点增设两格标志域ltag和rtag,令:
当Itag=0:表示lchild指向结点的左孩子;ltag=1:表示lchild指向结点的前驱结点。
当rtag=0:表示rchild指向结点的右孩子;rtag=1:表示rchild指向结点的后继结点。
为了将二叉树的所有空指针域都利用上,并且方便判断遍历操作何时结束,在存储的时候增设一个头结点,该头结点和其他结点类型相同,值域不存储值,初始化使其左指针域指向二叉树的根结点,右指针域指向自己。线索化完成后,让头结点的值域指向按某种顺序 遍历下的最后一个结点。而原二叉树在某种遍历顺序下的第一个结点的前驱线索和最后一个结点的后继线索都指向。
【结构体的定义】
//线索二叉树结点的定义
typedef char ElemType;
typedef struct BiThrNode
{ElemType data;int ltag;int rtag;struct BiThrNode* lchild;struct BiThrNode* rchild;
}BiThrNode,*BiThrTree;
4. 线索二叉树的操作
4.1. 建立一棵中序线索二叉树
【算法实现】
//建立中序线索二叉树
void InThreading(BiThrTree p, BiThrTree* pre)//递归算法
{if (p){InThreading(p->lchild, pre);//左子树线索化//前驱线索if (!p->lchild){p->ltag = 1;p->lchild = *pre;}elsep->ltag = 0;//后继线索if (!(*pre)->rchild){(*pre)->rtag = 1;(*pre)->rchild = p;}else(*pre)->rtag = 0;*pre = p;InThreading(p->rchild, pre);//右子树的线索化}
}
int InOrderThr(BiThrTree* head, BiThrTree T)//带头结点的中序线索二叉树的算法
{//基于中序遍历二叉树T,并将中序线索化,*head指向头结点//申请头结点的空间BiThrTree pre;if (!(*head = (BiThrTree)malloc(sizeof(BiThrNode))))return 0;//建立头结点(*head)->ltag = 0;(*head)->rchild = *head;//右指针回针if (!T)(*head)->lchild = *head;//若二叉树为空,则左指针回针else{(*head)->lchild = T;pre = *head;InThreading(T, &pre);//中序遍历进行中序线索化pre->rchild = *head; pre->rtag = 1;//最后一个结点线索化(*head)->rtag = 1;(*head)->rchild = pre;}return 1;
}
4.2. 在中序线索二叉树上查找任意结点的中序前驱结点
存在两种情况:
- 如果该结点的左标志为1,那么其左指针域指向的结点就是它的前驱结点。
- 如果该结点的左标志为0,那么说明该结点存在左孩子。由中序序列的定义,该左孩子的右子树的最后一个结点就是该结点前驱结点。即沿着其左孩子右指针向下找,当某个结点的右标志域为1时,它就是该结点的前驱结点。
【算法实现】
//在中序线索二叉树上查找任意结点的中序前驱结点
BiThrTree InPreNode(BiThrTree p)
{//在中序线索二叉树上寻找结点p的中序前驱结点BiThrTree pre = p->lchild;if (p->ltag == 0)//有左子树,找左子树最右下方的结点{while (pre->rtag == 0)pre = pre->rchild;}return pre;
}
4.3. 在中序线索二叉树上查找任意结点的中序后继结点
- 如果该结点的右标志为1,那么其右指针域指向的结点就是它的后继结点。
- 如果该结点的右标志为0,那么说明该结点存在右孩子。由中序序列的定义,该右孩子的左子树的最后一个结点就是该结点后继结点。即沿着其右孩子左指针向下找,当某个结点的左标志域为1时,它就是该结点的后继结点。
【算法实现】
//在中序线索二叉树上查找任意结点的中序后继结点
BiThrTree InPostNode(BiThrTree p)
{//在中序线索二叉树上寻找结点p的中序后继结点BiThrTree post = p->rchild;if (post->rtag == 0)//有右子树,找右子树最左下方的结点{while (post->ltag == 0)post = post->lchild;}return post;
}
4.4. 在中序线索二叉树上查找任意结点在先序下的后继结点
(1)若 * p为分支结点,待确定的先序下的后继结点有两种情况
①当p->ltag=0时,* p的左孩子为 * p的先序下的后继结点。
②当p->ltag=1且 p->rtag=0时,* p 的右孩子为 * p先序下的后继结点
(2)若 * p为叶子结点:
如果 * p的后继结点存在,则说明 一定是 * p某个祖先的右孩子结点;不存在则指向头结点。
【算法实现】
//在中序线索二叉树上查找任意结点在先序下的后继结点
BiThrTree InPrePostNode(BiThrTree head, BiThrTree p)
{//在中序线索二叉树上寻找结点p的先序下的后继结点,head为头结点BiThrTree post;if (p->ltag == 0)post = p->lchild;//*p有左子树else{post = p;while (post->rtag == 1 && post->rchild != head)post = post->rchild;post = post->rchild;}return post;
}
4.5. 在中序线索二叉树上查找任意结点在后序下的前驱结点
两种情况:
①存在右孩子,则右孩子是后序下的前驱结点;存在左孩子但是不存在右孩子,则左孩子是后序的前驱结点。
②是叶子结点,则它的在后序下的前驱结点是其某个祖先的左孩子,或者不存在则是头结点。
【算法实现】
//在中序线索二叉树上查找任意结点在后序结点下的前驱结点
BiThrTree InPostPreNode(BiThrTree head, BiThrTree p)
{//在线索二叉树上寻找结点p的后序下的前驱结点,head为头结点BiThrTree pre;if (p->rtag == 0)pre = p->rchild;else{pre = p;while (pre->ltag == 1 && pre->lchild != head)pre = pre->lchild;pre = pre->lchild;}return pre;
}
4.6. 在中序线索二叉树上查找值为x的结点
先找打中序序列中的第一个结点,在依次往后遍历整个中序线索二叉树。
【算法实现】
//在中序线索二叉树上查找值为x的结点
BiThrTree Search(BiThrTree head, ElemType x)
{//以head的头结点的中序线索二叉树中查找值为x的结点BiThrTree p = head->lchild;while (p->ltag == 0 && p != head)p = p->lchild;//找到中序序列的第一个结点while (p != head && p->data != x)p = InPostNode(p);if (p == head){printf("Not Found the data!\n");return 0;}else return p;
}
4.7. 中序线索二叉树上的插入与删除
插入和删除一个结点,都需要重新进行线索化。在这里讨论,插入一个结点使其成为右孩子。
【算法实现】
//在中序线索二叉树上的插入与删除
void InsertThrRight(BiThrTree s, BiThrTree p)
{//在中序线索二叉树中插入结点p,使其称为结点s的右孩子BiThrTree w;//将s变为p的中序前驱p->rchild = s->rchild;p->rtag = s->rtag;p->lchild = s;p->ltag = 1;//p变成s的右孩子s->rchild = p;s->rtag = 0;//当前s原来的右子树不为空,找到s的后继w,将w变成p的后继,并将p变成w的前驱if(p->rtag==0){w = InPostNode(p);w->lchild = p;}
}
5. 基于中序线索二叉树的遍历算法
//基于中序线索二叉树的遍历算法
void ThInOrder(BiThrTree head)
{//在中序线索二叉树上进行中序遍历BiThrTree p = head->lchild;while (p->ltag == 0)p = p->lchild;//找第一个结点while (p != head)//依序找后继结点{printf("%c ", p->data);p = InPostNode(p);}
}
void ThpreInOrder(BiThrTree head)
{//在中序线索二叉树上进行前序遍历BiThrTree p = head->lchild;while (p != head)//依序找打后继结点{printf("%c ", p->data);p = InPrePostNode(head, p);}
}
void ThpostInOrder(BiThrTree head)
{//在中序线索二叉树上进行后序遍历的逆序BiThrTree p = head->lchild;while (p != head)//依序找到前驱结点{printf("%c ", p->data);p = InPostPreNode(head, p);}
}
相关文章:

线索二叉树结构
线索二叉树结构1.线索二插树的作用2.线索二叉树的定义3.线索二叉树的结构4. 线索二叉树的操作4.1. 建立一棵中序线索二叉树4.2. 在中序线索二叉树上查找任意结点的中序前驱结点4.3. 在中序线索二叉树上查找任意结点的中序后继结点4.4. 在中序线索二叉树上查找任意结点在先序下的…...

6.网络爬虫——BeautifulSoup详讲与实战
网络爬虫——BeautifulSoup详讲与实战BeautifulSoup简介:BS4下载安装BS4解析对象Tag节点遍历节点find_all()与find()find_all()find()豆瓣电影实战前言: 📝📝此专栏文章是专门针对网络爬虫基础,欢迎免费订阅&#…...

Vue:路由管理模式
三种模式 Vue.js 的路由管理有三种模式: Hash 模式(默认):在 URL 中使用 # 符号来管理路由。例如,http://example.com/#/about。这个模式的好处是可以避免浏览器向服务器发送不必要的请求,并且不需要特殊…...

7个最好的PDF编辑器,帮你像编辑Word一样编辑PDF
PDF 是具有数字思维的组织的重要交流工具。提供高效的工作流程和更好的安全性,可以创建重要文档并与客户、同事和员工共享。文档的布局已锁定,因此无论在什么设备上查看,格式都保持不变。这是让每个人保持一致的好方法——尤其是那些使用Micr…...

【数据结构】树的介绍
文章目录前言树的概念及结构树的概念树的表示树在实际中的运用二叉树的概念及结构二叉树的概念现实中的二叉树特殊的二叉树二叉树的性质二叉树的储存结构顺序存储链式存储写在最后前言 🚩本章给大家介绍一下树。树的难度相对于前面的数据结构来说,又高了…...

CoreDNS 性能优化
CoreDNS 作为 Kubernetes 集群的域名解析组件,如果性能不够可能会影响业务,本文介绍几种 CoreDNS 的性能优化手段。合理控制 CoreDNS 副本数考虑以下几种方式:根据集群规模预估 coredns 需要的副本数,直接调整 coredns deployment 的副本数:k…...

前端三剑客常见面试题及其答案
目录 1、什么是 HTML? 2、什么是 CSS? 3、什么是 JavaScript? 4、什么是盒模型? 5、什么是浮动? 6、什么是定位? 7、什么是选择器? 8、什么是事件? 前端的三剑客指的是 HTML…...

【DFS专题】深度优先搜索 “暴搜”优质题单推荐 10道题(C++ | 洛谷 | acwing)
文章目录题单一、模板 [极为重要]全排列DFS组合型DFS指数DFS二、专题烤鸡 (指数BFS)P1088 火星人 【全排列】P1149 火彩棒 [预处理 ]P2036 PERKETP1135 奇怪的电梯 暴力P1036 [NOIP2002 普及组] 选数 (组合)P1596 [USACO10OCT]Lake Counting …...

微信小程序自定义组件生命周期有哪些?
微信小程序自定义组件的生命周期函数分为三类: 创建时执行的生命周期函数、更新时执行的生命周期函数和销毁时执行的生命周期函数。 下面是具体的生命周期函数及其触发时机: 创建时执行的生命周期函数: created:在组件实例刚刚…...

Linux就该这么学(六)
一、从“/”开始 Linux 系统中的文件和目录名称是严格区分大小写的。例如,root、rOOt、rooT 均代表不同的目录,并且文件名称中不得包含斜杠(/)。Linux 系统中的文件存储结构如下图所示。 在 Linux 系统中,最常见的目录…...

目标检测算法——YOLOv5/v7/v8改进结合涨点Trick之Wise-IoU(超越CIOU/SIOU)
超越CIOU/SIOU | Wise-IoU助力YOLO强势涨点!!! 论文题目:Wise-IoU: Bounding Box Regression Loss with Dynamic Focusing Mechanism 论文链接:https://arxiv.org/abs/2301.10051 近年来的研究大多假设训练数据中的…...

【蓝桥杯选拔赛真题39】python输出数字组合 青少年组蓝桥杯python 选拔赛STEMA比赛真题解析
目录 python输出数字组合 一、题目要求 1、编程实现 2、输入输出...

网络安全工程师做什么?
网络安全很复杂。数字化转型、远程工作和不断变化的威胁形势需要不同的工具和不同的技能组合。 系统必须到位以保护端点、身份和无边界网络边界。负责处理这种复杂安全基础设施的工作角色是网络安全工程师。 简而言之,网络安全工程师是负责设计和实施组织安全系…...

总结:K8S运维常用命令
一、部署./kubectl apply -f biz-healing-pod.yaml 二、查看部署的资源1、podkubectl get pod -A:获取所有pod没有IP?用-o wide参数看详细信息:./kubectl get pod -n deepflow -o wide2、service查看hubble-manager命名空间下有哪些service/d…...

你是真的“C”——进行动态内存分配库函数的使用详解
你是真的“C”——申请动态空间库函数的使用详解😎前言🙌一、为什么需要动态内存分配?💞free 函数😘malloc 库函数😘calloc 库函数😘realloc 库函数😘总结撒花💞…...

Python|蓝桥杯进阶第五卷——数论
欢迎交流学习~~ 专栏: 蓝桥杯Python组刷题日寄 蓝桥杯进阶系列: 🏆 Python | 蓝桥杯进阶第一卷——字符串 🔎 Python | 蓝桥杯进阶第二卷——贪心 💝 Python | 蓝桥杯进阶第三卷——动态规划 ✈️ Python | 蓝桥杯进阶…...

用Python实现单例模式
什么是单例模式单例模式是指在内存中只会创建且仅创建一次对象的设计模式。在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象…...

交叉编译说明:工具链安装和环境变量配置
目录 一 简单了解交叉编译 ① 什么是交叉编译 ② 为什么需要交叉编译 ③ 宿主机和目标机 二 搭建交叉编译工作环境 ① 安装工具链 ② 配置环境变量 ● 配置临时环境变量 ● 配置永久环境变量 三 交叉编译宿主机和目标机 ● 宿主机编译生成的可执行文件下载到目…...

文件上传的多种利用方式
文件上传的多种利用方式 文件上传漏洞除了可以通过绕过检测进行webshell的上传之外,还有多种其它的漏洞可以进行测试。 XSS漏洞 文件名造成的XSS 当上传任何文件时,文件名肯定是会反显示在网页上,可以使用 XSS Payload做文件名尝试将其上传到…...

盘一盘C++的类型描述符(二)
先序文章请看 盘一盘C的类型描述符(一) 稍微组合一下的复杂类型 数组指针类型的数组类型 数组的指针类型我们已经了解了,那么,以这种类型作为元素的数组类型怎么搞? using type int (*)[3]; // 元素类型是数组指针…...

慎投,Frontiers这本期刊显示on hold中
什么是“On Hold”? 该期刊因为质量问题正在被进行重新评估;在重新评估过程中,不会检索新发表的文章。该期刊因为质量问题正在被进行重新评估;在重新评估过程中,不会检索新发表的文章。根据选择标准,在最严…...

Winform控件开发(21)——ProgressBar(史上最全)
一、属性 1、Name 用于获取控件对象 2、Anchor 锚定控件对于父控件的位置 3、BackColor 背景色 4、ContextMenuStrip 关联的上下文菜单 5、Cursor 鼠标移动到控件上显示的光标 6、Dock 停靠在父控件的位置 7、Enabled 是否启动该控件,false时事件都不能触发 8、…...

校招失败后,在外包公司熬了 2 年终于进了字节跳动,竭尽全力....
其实两年前校招的时候就往字节投了一次简历,结果很明显凉了,随后这个理想就被暂时放下了,但是这个种子一直埋在心里这两年除了工作以外,也会坚持写博客,也因此结识了很多优秀的小伙伴,从他们身上学到了特别…...

UniApp + SpringBoot 实现接入支付宝支付功能和退款功能
一、支付宝开放平台设置 注册支付宝支付功能需要个体工商户或企业才可以!需要有营业执照才能去申请哦! 1、登录到控制台 进入支付宝开放平台 控制台 2、开发设置 3、产品绑定APP支付 如果没有绑定APP支付就会报商家订单参数异常,请重新发起…...

初识进程
文章目录一、进程的概念1. 进程是什么及进程的管理2. Linux 下的 pcb3. 系统调用接口 getpid 和 getppid4. 系统调用接口 fork一、进程的概念 1. 进程是什么及进程的管理 在 Linux下 ./binaryfile 运行一个程序或者在 Windows下双击运行一个程序时,程序就变成了一个…...

SOAP传输协议
一.HTTP传输协议 超文本传输协议(HyperText Transfer Protocol,缩写:HTTP),它是基于请求-响应的模式协议,客户端发出请求,服务器端给出响应并返回请求内容。方法如下,HTTP传输协议常…...

<Linux>进程控制
进程控制 文章目录进程控制一、进程创建1.fork函数认识2.写时拷贝3.fork常规用法4.fork调用失败的原因二、进程终止1.进程退出场景2.进程退出码3.进程退出的方式三、进程等待1.进程等待是什么?2.进程等待的必要性3.进程等待的方法3.1.wait函数3.2.waitpid函数4.如何…...

有手就行 -- 搭建图床(PicGo+腾讯云)
🍳作者:贤蛋大眼萌,一名很普通但不想普通的程序媛\color{#FF0000}{贤蛋 大眼萌 ,一名很普通但不想普通的程序媛}贤蛋大眼萌,一名很普通但不想普通的程序媛🤳 🙊语录:多一些不为什么的…...

“蓝桥杯”递推和递归(一)——取数位
1. 算法简介 递推和递归虽然叫法不同,但它们的基本思想是一致的,在很多程序中,这两种算法可以通用,不同的是递推法效率更高,递归法更方便阅读。 (1)递推法 递推法是一种重要的数学方法&#…...

蓝桥杯·3月份刷题集训Day02
本篇博客旨在记录自已打卡蓝桥杯3月份刷题集训,同时会有自己的思路及代码解答希望可以给小伙伴一些帮助。本人也是算法小白,水平有限,如果文章中有什么错误之处,希望小伙伴们可以在评论区指出来,共勉💪。 文…...