二叉树—先后序线索化和先后序线索遍历

有了上篇文章的基础,先序和后序的线索化逻辑一样。

代码如下:

void preOrderThreadTree(TreeNode* T,TreeNode** pre) {if (T == NULL) {;}else {//printf("%c ", T->val);if (T->lchild == NULL) {T->ltag = 1;T->lchild = *pre;}if (*pre != NULL && (*pre)->rchild == NULL) {(*pre)->rtag = 1;(*pre)->rchild = T;}*pre = T;TreeNode* right = T->rchild;if (T->ltag != 1) {preOrderThreadTree(T->lchild, pre);}if (T->rtag != 1) {preOrderThreadTree(right, pre);}}
}
void postOrderThreadTree(TreeNode* T, TreeNode** pre) {if (T == NULL) {}else {postOrderThreadTree(T->lchild, pre);postOrderThreadTree(T->rchild, pre);if (T->lchild == NULL) {T->ltag = 1;T->lchild = *pre;}if (*pre != NULL && (*pre)->rchild == NULL) {(*pre)->rtag = 1;(*pre)->rchild = T;}*pre = T;}
}

        就是调整递归函数的顺序,就可以实现先序和后序的线索化,但是有一点需要注意,在先序遍历中,因为我们线索化之后会改变节点的左右孩子。举个例子:

        T的左孩子为空,所以T指向自己的前驱*pre,然后执行 preOrderThreadTree(T->lchild, pre);,但是此时的 T->lchild 是已经改变过的而不是NULL,所以如果进入递归,函数会崩溃,T不能正常遍历。所以,当T->ltag等于1时,就不进入递归。

        同样,当树即将遍历完时,如果没有考虑到树节点右孩子的改变,就也可能出现死递归的情况。

        如图所示,先序遍历顺序;A B D E C F。这两个条件分别保护了在左右孩子改变的情况下可以正常进行递归的,否则就会回到前驱节点造成死递归。

        那么为什么后序没有这样的问题,仔细观察会发现,后序遍历,递归操作在线索化之前,也就是说在改变左右孩子之前就已经遍历到目标节点,而先序的问题在于需要靠没有改变的左右节点遍历,但是中途有改变左右孩子的操作,所以遍历可能会出现问题。

接下来就是线索二叉树的遍历:

首先是先序线索二叉树的先序线索遍历:

TreeNode* GetNext(TreeNode* node) {if (node->ltag !=1) {node = node->lchild;}else {node = node->rchild;}return node;
}
int main() {char array[15] = "ABD##E##CF###";int index = 0;TreeNode* pre = NULL;TreeNode* T;MyTreeCreat(&T, array, &index);preOrderThreadTree(T,&pre);pre->rtag = 1;pre->rchild = NULL;for (TreeNode* node = T; node != NULL; node = GetNext(node)) {printf("%c ", node->val);}return 0;
}

        首先输入的是根节点,因为先序遍历是 根->左孩子->右孩子,所以只要 node->ltag !=1,就说明有左孩子,先序顺序根节点的下一个就是左孩子,如果没有左孩子,就指向右孩子,无论右孩子是真存在,还是不存在,都指向的是先序遍历的后继,所以,这就是先序遍历线索树。遍历主体是for循环。

接下来是后序线索二叉树的后序遍历:

void postOrderTraversal(PostThreadNode* root) {if (root == NULL) return;// 找到后序遍历的第一个节点PostThreadNode* cur = root;while (cur->left || cur->right) {if (cur->left) {cur = cur->left;} else if (cur->right) {cur = cur->right;}}// 遍历while (cur != NULL) {printf("%c ", cur->data);// 通过线索找到后继节点if (cur->right && (cur->right->left == cur || cur->right->right == cur)) {cur = cur->right;} else {cur = cur->successor;}}
}

        很抱歉我没有完全用之前的方法搞懂如何进行后序线索树的后序遍历,这是我在网上找到的示例代码。

这就是文章的全部内容了,希望对你有所帮助,如有错误欢迎指出。

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

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

相关文章

计算机笔记14(续20个)

230.色彩的种类就是色相 饱和度就是彩度除以明度 231.RISC是精简指令集,CISC是复杂指令集 232.世界上第一台数字计算机,奠定了至今仍在使用计算机体系结构 233.数据传输中,电路交换的传输延迟最小 234.定点整数的小数点约定在最低…

CTF-web-攻防世界-3

1、inget (1)、进入网站,提示传入id值 (2)、用一些闭合方式,返回都一样。 (3)、尝试万能密码。获得flag 2、mfw (1)、页面没有什么特殊的异常,使用dirsearch进行目录扫描,有一些.git文件。看样子是.git文件泄露。 使用githa…

7款好用到离谱的神级App推荐!

AI视频生成:小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/ 转眼间,2024年已经是下个月。最近有很多小伙伴的咨询,我也赶紧整理了7款好用的软件,希望对大家有所帮助。 …

Git简介以及下载安装和配置

Git介绍 什么是版本控制?什么是Git?什么是集中式版本控制(了解)分布式版本控制工作流程 Git的安装与配置注册邮箱以及用户名(方便远程使用)初始化项目Git在ideal上的使用(本地) 什么是版本控制? ​ 版本控制是指对软件开发过程中各种程序代码,控制文件及说明文档等文件变更…

【C语言实现线程池】

创建一个线程池是提高多线程应用程序性能的有效方法。一个线程池中包含一定数量的工作线程,这些线程可以复用来处理多个任务,避免了频繁创建和销毁线程所带来的开销。 下面是一个基础的线程池实现的框架,使用C语言和POSIX线程库(pthread)。这…

lodash已死?radash库方法介绍及源码解析 —— 对象方法篇

assign:递归合并两个对象 使用说明 功能说明:类似于 JavaScript 的 Object.assign 方法,用于将 override 对象的属性和值复制到 initial 对象中。如果属性值是对象,则递归地进行赋值。 参数:初始对象、覆盖对象。 返…

清理mysql binglog文件

mysql随着使用时间的推移,binglog文件会越来越大,比如我们的oa系统,上线4年多了,最近总有磁盘空间满影响系统正常使用的情况出现。检查后发现binglog是罪归祸首。 binglog文件最好不要采用应删除的方式清理,如下方式可…

LLVM Visual Studio构建

cd llvm-project-main cmake -S llvm -B build -G "Visual Studio 16 2019" -DLLVM_ENABLE_PROJECTSclang-tools-extra -DLLVM_ENABLE_PROJECTSclang .

spring cache(三)demo

一、入门demo 1、pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.o…

ACL组网实验(华为)

思科设备参考&#xff1a;ACL组网实验&#xff08;思科&#xff09; 更多内容参考&#xff1a;华为ACL配置&#xff08;基本ACL高级ACL综合应用&#xff09; 技术简介 ACL&#xff08;Access Control List&#xff09;技术是一种基于包过滤的流控制技术&#xff0c;主要用于…

ML307R OpenCPU UART使用

一、串口使用流程图 二、串口相关函数介绍 三、实现串口收发 一、串口使用流程图 OneMO ML307R模组提供了2路UART给开发者用于通讯开发&#xff0c;以及1路DBG UART用于log的打印。UART Demo示例可以在SDK&#xff1a;examples\uart\src\cm_demo_uart.c中查看。 串口使用流…

Vue3实战笔记(42)—Vue + ECharts:流量数据可视化的强大组合

文章目录 前言vue3使用echarts标准demo&#xff1a;总结 前言 在前端开发中&#xff0c;数据可视化已经成为了一个不可或缺的部分。Vue.js作为一个轻量级且易于上手的渐进式JavaScript框架&#xff0c;与ECharts这个强大的数据可视化库的结合&#xff0c;使得在Vue应用中构建交…

windows下nginx配置https证书

1、制作证书 1.1 安装工具openSSL。下载地址&#xff1a;http://slproweb.com/products/Win32OpenSSL.html Win64OpenSSL_Light-3_1_0.exe安装&#xff08;假定安装位置在 d:\openSSL\&#xff09; 1.2 配置openSSL环境。 新建系统变量OpenSSL值为d:\openSSL\bin&#xff0c;相…

java继承(构造器)使用细节3

那么我们怎么来选择用父类的 有参构造器 和无参构造器泥&#xff1f; 就可以不写 或只写super() 并且如像爸爸的爸爸还有爸爸&#xff0c;还有构造。所以会一直调用到爷爷的构造。 细节2 直接继承指的是儿子和爸爸&#xff0c;爸爸和爷爷

Python 渗透测试:Redis 数据库 弱密码测试.(6379端口)

什么是 Redis 数据库 Redis (Remote Dictionary Server) 是一个开源的、内存中的数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息中间件。它支持多种类型的数据结构,如字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等&#xff0…

View function mapping is overwriting an existing endpoint function: home_page

这个错误是因为在你的 Flask 应用中,你定义了两个或多个视图函数,它们使用了相同的 endpoint 名称。Flask 不允许多个视图函数使用相同的 endpoint 名称,因为这会导致冲突。 通常,这个错误会出现在以下几种情况下: 你在不同的路由装饰器中使用了相同的 endpoint 名称。你…

Xilinx(AMD) FPGA通过ICAP原语读取芯片IDCODE实现方法

1 概述 Xilinx每种型号的FPGA芯片都有一个唯一的IDCODE与之对应&#xff0c;同一型号不同封装的IDCODE是相同的。IDCODE的获取方法包括JTAG、ICAP原语、AXI_HWICAP IP核等。获取IDCODE常用于根据芯片型号改变代码的功能&#xff0c;或者对代码进行授权保护&#xff0c;只能在指…

Java使用apache.poi生成excel插入word中

加油&#xff0c;新时代打工人&#xff01; 工作需求&#xff0c;上个文章我们生成好的word&#xff0c;这次将生成好的excel表格数据&#xff0c;插入word中。需要准备好excle数据&#xff0c;然后插入到word中。 最后个需要&#xff0c;就是把这些生成好的word文档转成pdf进行…

【LeetCode面试经典150题】104. 二叉树的最大深度

一、题目 104. 二叉树的最大深度 - 力扣&#xff08;LeetCode&#xff09; 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 二、思路 二叉树的题目就是递归&#xff0c;怎么递归呢&#xff1f;要求…