线索二叉树结构
线索二叉树结构
- 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]; // 元素类型是数组指针…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
