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

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

代码如下:

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.rhkb.cn/news/331597.html

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

相关文章

翻译《The Old New Thing》- What‘s the deal with the EM_SETHILITE message?

Whats the deal with the EM_SETHILITE message? - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20071025-00/?p24693 Raymond Chen 2007年10月25日 简要 文章讨论了EM_SETHILITE和EM_GETHILITE消息在文档中显示为“未实现”的原因。这些…

Python数字比大小获取大的数

目录 一、引言 二、数字比较的基本语法 三、获取较大的数 使用条件语句 使用内置函数 四、处理特殊情况 比较非数字类型 处理无穷大和NaN 五、应用实例 在游戏开发中比较分数 在数据分析中找出最大值 六、优化与性能 七、总结 一、引言 在Python编程的广阔天地中…

Redis 性能管理

一、Redis 性能管理 #查看Redis内存使用 172.168.1.11:6379> info memory 1. 内存碎片率 操作系统分配的内存值 used_memory_rss 除以 Redis 使用的内存总量值 used_memory 计算得出。内存值 used_memory_rss 表示该进程所占物理内存的大小,即为操作系统分配给…

【qt】纯代码界面设计

界面设计目录 一.界面设计的三种方式1.使用界面设计器2.纯代码界面设计3.混合界面设计 二.纯代码进行界面设计1.代码界面设计的总思路2.创建项目3.设计草图4.添加组件指针5.初始化组件指针6.添加组件到窗口①水平布局②垂直布局③细节点 7.定义槽函数8.初始化信号槽9.实现槽函数…

Sam Altman微软Build 2024最新演讲:AI可能是下一个移动互联网

大家好,我是木易,一个持续关注AI领域的互联网技术产品经理,国内Top2本科,美国Top10 CS研究生,MBA。我坚信AI是普通人变强的“外挂”,所以创建了“AI信息Gap”这个公众号,专注于分享AI全维度知识…

Tomcat部署项目的方式

目录 1、Tomcat发布项目的方式 方式1: 直接把项目发布到webapps目录下 方式2:项目发布到ROOT目录 方式3:虚拟路径方式发布项目 方式4:(推荐)虚拟路径,另外的方式! 方式5:发布多个网站 1、…

无界鼠标与键盘,如何轻松控制多台电脑

简介 在软件开发领域,高效地管理多台电脑是至关重要的。Mouse without Borders软件为开发人员提供了一种便捷的解决方案,使他们能够轻松地在多台电脑之间共享鼠标和键盘。不仅如此,Mouse without Borders还提供了许多高级功能,如…

STM32F1之OV7725摄像头

目录 1. 摄像头简介 2. OV7725 摄像头简介 3. OV7725 引脚 4. OV7725 功能框架图 5. SCCB时序 5.1 SCCB 的起始、停止信号及数据有效性 5.2 SCCB 数据读写过程 1. 摄像头简介 在各类信息中,图像含有最丰富的信息,作为机…

谈谈你对 vue 的理解 ?

1.谈谈你对 vue 的理解 ? 官方: Vue是一套用于构建用户界面的渐进式框架,Vue 的核心库只关注视图层 2. 声明式框架 Vue 的核心特点,用起来简单。那我们就有必要知道命令式和声明式的区别! 早在 JQ 的时代编写的代码都是命令式的,命令式框架重要特点就是关注过程 声明…

world machine学习笔记(3)

打开 可以打开场景设置,项目设置平铺构建设置 场景设置: 输出范围 设置中心点和范围 设置分辨率 项目设置: 设置地图颜色,单位,最高地形高度 点击这个图形进行预览设置 该按钮还有其他的功能 world machine基础流程…

LeetCode算法题:42. 接雨水(Java)

题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例 1: 输入:height [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3…

分享一个用AI降本的思路,不懂代码也能上手

如何用AI解决实际的业务问题? 生财圈友我来利用ChatGPT做算法建模,每年为公司省下6万元。 今天他将分享通过ChatGPT进行数据分析的思路,从最开始定义问题到最终数据论证。 上手的实操过程门槛并不高,但可以实现把官方电商平台的…

huggingface笔记: accelerate estimate-memory 命令

探索可用于某一机器的潜在模型时,了解模型的大小以及它是否适合当前显卡的内存是一个非常复杂的问题。为了缓解这个问题,Accelerate 提供了一个 命令行命令 accelerate estimate-memory。 accelerate estimate-memory {MODEL_NAME} --library_name {LIBR…

Ubuntu22.04虚拟机设置静态IP

虚拟机设置静态IP 按下电脑的 “win”键,在弹出的输入框中输入“控制面板”,选中控制面板 1.选择 “网络和Internet” 2.选择 “网络和共享中心” 3.选择 “更改适配器设置” 4.选择 “VMnet8”,双击打开 5.选择 “属性” 找到 “Internet …

Reactor设计模式

Reactor设计模式 Reactor模式称为反应器模式或应答者模式,是基于事件驱动的设计模式,拥有一个或多个并发输入源,有一个服务处理器和多个请求处理器,服务处理器会同步的将输入的请求事件以多路复用的方式分发给相应的请求处理器。…

Qt 界面上字体自适应控件大小 - 随控件缩放

Qt 界面上字体自适应控件大小 - 随控件缩放 引言一、设计思路二、进阶版大致思路三、参考链接 引言 Qt控件自适应字体大小可以用adjustSize()函数,但字体自适应控件大小并没有现成的函数可调. - 本文实现了按钮上的字体随按钮大小变化而变化 (如上图所示) - 其他控件…

10款免费黑科技软件,强烈推荐!

1.AI视频生成——巨日禄 网页版https://aitools.jurilu.com/ "巨日禄 "是一款功能强大的文本视频生成器,可以快速将文本内容转换成极具吸引力的视频。操作简单,用户只需输入文字,选择喜欢的样式和模板, “巨日禄”就会…

Python | Leetcode Python题解之第111题二叉树的最小深度

题目: 题解: class Solution:def minDepth(self, root: TreeNode) -> int:if not root:return 0que collections.deque([(root, 1)])while que:node, depth que.popleft()if not node.left and not node.right:return depthif node.left:que.appen…

Qt学习记录(14)线程

前言&#xff1a; 我的臀部已经翘到可以顶起一屁股债了 为什么要使用线程 什么时候用线程 复杂的数据处理 头文件.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimer>//定时器头文件QT_BEGIN_NAMESPACE namespace Ui { class Widget; }…

Hive安装教程

前置条件:hadoop&mysql docker容器安装mysql-CSDN博客 以下的/opt/bigdata目录根据自己实际情况更改 1.上传hive包并解压 tar -zxvf apache-hive-3.1.3-bin.tar.gz -C /opt/bigdata/ 2.修改路径 mv /opt/bigdata/apache-hive-3.1.3-bin/ hive cd /opt/bigdata/hive/…