05 二叉树前序/中序/后序线索化和找前驱、后继

news2024/10/5 16:24:46

1. 线索化代码

线索化需要先序/中序/后续遍历的过程,多了访问到节点时指针指向的问题

二叉树形状和运行结果

在这里插入图片描述
在这里插入图片描述

主函数

#include "func.h"

// 二叉树线索化(便于找前驱和后继节点)
// 1. 二叉树先序线索化
// 2. 二叉树中序线索化
// 3. 二叉树后序线索化

// 中序线索化
// 需要有一个前驱节点指针
// 1. 进行中序序遍历,当访问到某节点时,进行判断:
//       (1) 如果左子树为空,则让左孩子指向pre
//       (2) 如果pre的右子树为空,则让右孩子指向当前访问的节点
// 2. 让pre指向当前节点,进入下一次遍历

BiNode *pre = NULL;   // 全局变量

void InThread(BiTree &tree){
    if (tree!=NULL){
        InThread(tree->left);
        if(tree->left == NULL){
            tree->ltag = 1;
            tree->left = pre;
            if (pre==NULL) printf("\n%c.pre --> NULL\n",tree->data.value);
            else printf("%c.pre---> %c\n",tree->data.value,pre->data.value);
        }
        if(pre != NULL && pre->right == NULL){
            pre->right = tree;
            pre->rtag = 1;
            printf("%c.post---> %c\n",pre->data.value,tree->data.value);
        }
        pre = tree;
        InThread(tree->right);
    }
}

// 先序线索化
// 需要注意的是,当把节点左孩子链接为该节点前驱,那么再使用tree->left访问左孩子就造成访问错误,需要额外加ltag判断

void PreThread(BiTree &tree){
    if(tree!=NULL){
        if(tree->left == NULL){
            tree->left = pre;
            tree->ltag = 1;
            printf("%c.pre---> %c\n",tree->data.value,pre->data.value);
        }
        if(pre!=NULL && pre->right == NULL){
            tree->right = pre;
            tree->rtag = 1;
            printf("%c.post---> %c\n",pre->data.value,tree->data.value);
        }
        pre = tree;
        if (tree->ltag == 0) PreThread(tree->left);
        PreThread(tree->right);
    }
}

void PostThread(BiTree &tree){
    if(tree!=NULL){
        PostThread(tree->left);
        PostThread(tree->right);
        if(tree->left == NULL){
            tree->left = pre;
            tree->ltag = 1;
            if (pre==NULL) printf("\n%c.pre --> NULL\n",tree->data.value);
            else printf("%c.pre---> %c\n",tree->data.value,pre->data.value);
        }
        if(pre!=NULL && pre->right == NULL){
            tree->right = pre;
            tree->rtag = 1;
            printf("%c.post---> %c\n",pre->data.value,tree->data.value);
        }
        pre = tree;
    }
}




// Demo:
//                  A
//              B       C
//           D    E  NULL   F
// 中序遍历:DBEACF
// 线索化: D.pre->NULL; D.post=B; E.pre->B; E.post->A; C.pre->A; F.pre->C
// 先序遍历: ABDECF
// 线索化: D.pre->B; E->pre=D; D->post=E; C->pre=E; C->post=C
int main() {
    printf("---------------------\n");
    BiTree tree;
    getDemo(tree);
    InOrder(tree);
    InThread(tree);
    pre=NULL;
    printf("---------------------\n");
    BiTree tree2;
    getDemo(tree2);
    PreOrder(tree2);
    printf("\n");
    PreThread(tree2);
    printf("---------------------\n");
    pre = NULL;
    BiTree tree3;
    getDemo(tree3);
    PostOrder(tree3);
    PostThread(tree3);
    return 0;
}

头文件和其它源文件

#include "func.h"

void init(BiTree &tree){
    tree = (BiNode*) malloc(sizeof(BiNode));
    tree->left = NULL;
    tree->right = NULL;
    tree->ltag = tree->rtag = 0;
}

BiNode* create_node(Element elem){
    BiNode *p_node = (BiNode*) malloc(sizeof(BiNode));
    p_node->data = elem;
    p_node->left = p_node->right = NULL;
    p_node->ltag = p_node->rtag = 0;
    return p_node;
}

BiTree getDemo(BiTree &tree){
    // Demo:
    //                  A
    //              B       C
    //           D    E  NULL   F
    //
    init(tree);
    Element A,B,C,D,E,F;
    A.value = 'A';
    B.value = 'B';
    C.value = 'C';
    D.value = 'D';
    E.value = 'E';
    F.value = 'F';
    BiNode *pb = create_node(B);
    BiNode *pc = create_node(C);
    BiNode *pd = create_node(D);
    BiNode *pe = create_node(E);
    BiNode *pf = create_node(F);
    tree->data = A;
    tree->left = pb;
    tree->right = pc;
    pb -> left = pd;
    pb->right = pe;
    pc->right = pf;
}


void visit(BiNode *node){
    printf("%c\t",node->data);
}

void PreOrder(BiTree tree){
    if (tree != NULL){
        visit(tree);
        PreOrder(tree->left);
        PreOrder(tree->right);
    }
}

void InOrder(BiTree tree){
    if (tree != NULL){
        InOrder(tree->left);
        visit(tree);
        InOrder(tree->right);
    }
}

void PostOrder(BiTree tree){
    if (tree != NULL){
        PostOrder(tree->left);
        PostOrder(tree->right);
        visit(tree);
    }
}



//
// Created by 64516 on 2023/1/25.
//

#ifndef ORDER_01_FUNC_H
#define ORDER_01_FUNC_H


#include <stdio.h>
#include <stdlib.h>



typedef struct Element{
    char value;
};

typedef struct BiNode{
    Element data;
    BiNode *left,*right;  // 可以将节点左右指针初始化为NULL吗?
    bool ltag,rtag;
}BiNode,*BiTree;

BiTree getDemo(BiTree &tree);
void visit(BiNode *node);
void PreOrder(BiTree tree);
void InOrder(BiTree tree);
void PostOrder(BiTree tree);

#endif //ORDER_01_FUNC_H

2. 在二叉树线索化后找节点前驱/后继

中序线索二叉树

中序线索二叉树找中序前驱
如果ltag=0,则子树有左孩子,前驱为左子树最右的节点
>

中序线索二叉树找中序后继
如果rtag=0,则节点有右孩子,后继为子树最左的节点在这里插入图片描述

先序线索二叉树

先序线索二叉树找先序前驱
若ltag=1可以直接找到,若ltag=0,节点有左孩子,该节点在向下子树是第一个被访问的节点,无法找到该节点的前驱,除非该二叉树为三叉链表可以链接到父节点
先序线索二叉树找先序后继
若rtag=0则有右孩子,此时节点有左孩子则左孩子为后继,没有左孩子则右孩子为后继

后序线索二叉树

后续线索二叉树找后续前驱
若ltag=0则有左孩子,此时没有右孩子则左孩子为前驱,有右孩子则右孩子为前驱
后续线索二叉树找后续后继
若rtag=1可以直接找到,若rtag=0则节点有右孩子,该节点在向下子树内是最后访问的,无法找到该节点的后继,除非该二叉树为三叉链表。

三叉链表时的补充:
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

《MySQL》MySQL简单操作

最近开始了新的学习进度 进入MySQL数据库的学习 目录 一、MySQL启动方法 1.使用MySQL启动 2.使用cmd启动 二、数据库的简单操作命令 显示当前服务器上有哪些数据库 创建新的数据库 删除数据库 选中数据库 三、数据表的操作 数据类型 四、表的简单操作 查看数据库中的…

Java多线程-线程的生命周期

Java多线程-线程的生命周期 线程的状态 New 表示线程已创建&#xff0c;没启动的状态此时已经做了一些准备工作&#xff0c;还没有执行run方法中代码 Runnable 调用start方法之后的状态&#xff0c;表示可运行状态(不一定正在运行&#xff0c;因为调用start方法之后不一定立…

分享148个ASP源码,总有一款适合您

ASP源码 分享148个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 148个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/1e2PvBmXxZA8C3IelkP8ZtQ?pwdj7lp 提取码&#x…

node.js 安装步骤

1、下载安装包 Node.js 官方网站下载&#xff1a;Node.js 选择操作系统对应的包&#xff1a; 下载完成&#xff0c;安装包如下&#xff1a; 2、安装Node 打开安装&#xff0c;傻瓜式下一步即可&#xff1a; 选择安装位置&#xff0c;我这里装在D盘下&#xff1a; 安装成功&…

图和树基础算法笔记

图的大部分知识在《离散数学》中都已经学习了&#xff0c;所以我主要放一些不知道的知识 常用概念 有很少边或弧&#xff08;如 e < n log n&#xff0c;e指边数&#xff0c;n指顶点数&#xff09;的图称为稀疏图&#xff0c;反之称为稠密图。完全图&#xff1a;每个顶点的…

[引擎开发] 现代图形API - dx12篇

本文将从性能优化的角度去阐述像dx12这样的现代图形API的一些设计理念。 当我们深入优化渲染管线的时候&#xff0c;我们会发现存在的几个瓶颈主要是这样的&#xff1a; ① 线程存在不合理的等待 ② CPU向GPU编码传输数据非常耗时 ③ CPU频繁地切换渲染上下文非常耗时 因此有时…

Python---库的使用

专栏&#xff1a;python 个人主页&#xff1a;HaiFan. 专栏简介&#xff1a;本专栏主要更新一些python的基础知识&#xff0c;也会实现一些小游戏和通讯录&#xff0c;学时管理系统之类的&#xff0c;有兴趣的朋友可以关注一下。 库前言标准库使用import导入模块例1例2例3 文件…

老司机经验分享:生产级中间件系统架构设计实践

目录 1、Master-Slave架构2、异步日志持久化机制3、检查点机制&#xff1a;定时持久化全量数据4、引入检查点节点5、总结 & 思考 这篇文章&#xff0c;给大家来聊一个生产级的中间件系统的架构设计实践&#xff0c;希望给对中间件系统感兴趣的同学一点启发。 1、Master-S…

【Java|golang】1663. 具有给定数值的最小字符串---int32切片类型转化string

小写字符 的 数值 是它在字母表中的位置&#xff08;从 1 开始&#xff09;&#xff0c;因此 a 的数值为 1 &#xff0c;b 的数值为 2 &#xff0c;c 的数值为 3 &#xff0c;以此类推。 字符串由若干小写字符组成&#xff0c;字符串的数值 为各字符的数值之和。例如&#xff…

修改VS2015的文件编码格式为utf8,解决在Ubuntu下中文输出为乱码的问题

开发环境&#xff1a; Windows系统&#xff1a;Windows 10 家庭版&#xff0c;VS2015社区版 Linux系统&#xff1a;Ubuntu 22.04 LTS Server版&#xff0c;gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04) 今天编写跨平台的代码&#xff0c;在Windows下用VS2015编写&a…

C++ AVL树

前言 众所周知红黑树是由AVL树改进得来的&#xff0c;想要深入学习哈希表的底层存储那么AVL的学习就相当有必要了。 本来想将AVL的插入删除都能实现&#xff0c;但是在写删除功能时碰到了难题和Bug&#xff0c;所以暂时先给出插入的实现过程&#xff0c;和删除功能的实现思路 …

【日常系列】LeetCode《29·动态规划4》

数据规模->时间复杂度 <10^4 &#x1f62e;(n^2) <10^7:o(nlogn) <10^8:o(n) 10^8<:o(logn),o(1) 内容 字符串/数组dp问题 动态规划中的双状态问题 lc 139【top100】&#xff1a;单词拆分 https://leetcode.cn/problems/word-break/ 提示&#xff1a; 1 <…

Qt扫盲-QHttpPart类理论总结

QHttpPart类理论总结一、概述二、使用1. 设置头2. 设置内容一、概述 QHttpPart类保存一个主体部分&#xff0c;用于HTTP multipart MIME消息中(由QHttpMultiPart类表示)。 QHttpPart由一个头块和一个数据块组成&#xff0c;它们由两个连续的新行相互分隔。一个部分的例子是: …

智能合约开发——Sui/Move vs. Solana/Rust

1. 引言 前序博客有&#xff1a; zkMove——针对Move合约生态的zkVM 定位为高性能L1的Aptos和Sui&#xff0c;均采用Move合约编程语言。Solana也定位为高性能L1&#xff0c;但其采用Rust合约编程语言。本文重点对比Sui/Move和Solana/Rust合约编程语言。【Aptos/Move为不同的M…

三、Java框架之SpringMVC1_MVC基础

文章目录1. SpringMVC简介1.1 回顾Servlet技术1.2 SpringMVC入门案例步骤1&#xff1a;创建javaweb项目&#xff0c;并导入jar包步骤2&#xff1a;创建Controller步骤3&#xff1a;创建SpringMVC的配置文件步骤4&#xff1a;使用配置类替换web.xml步骤5&#xff1a;启动项目并访…

PyTorch深度学习实践第二讲线性模型

目录监督学习四步骤线性模型泛化代码作业监督学习四步骤 DataSet&#xff08;数据集&#xff09;Model&#xff08;模型选择和设计&#xff0c;例如神经网络&#xff0c;决策树等&#xff09;Training&#xff08;大部分模型都需要训练&#xff0c;都有些例如KNN不需要训练&am…

BFS(四)127. 单词接龙、433. 最小基因变化

目录 127. 单词接龙 433. 最小基因变化 127. 单词接龙 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk&#xff1a; 每一对相邻的单词只差一个字母。 对于 1 < i < k 时&am…

Qt 6.x中Qt Quick简介及示例

Qt Quick首次在Qt 4.7和Qt Creator 2.1中引入&#xff0c;是一种高级UI技术。 Qt Quick模块是用于编写QML(Qt Meta-Object Language, Qt元对象语言)应用程序的标准库。Qt QML模块提供了QML引擎(engine)和语言基础设施&#xff0c;而Qt Quick模块提供了使用QML创建用户界面…

LCD timing的理解

前言 LCD的时序,之前也有介绍过(深入裸机),但是在介绍这些参数的时候是以感性的认识去理解的,而且多少有些错误,我们以内核文档中的描述为准(Documentation/fb/framebuffer.txt),在结合全志平台来重新正确的理解这些参数。 我们在看下文档中的解释: The frame buffe…

【学习笔记】智能合约引擎

图片来源&#xff1a;https://www.researchgate.net/publication/336453428_Detecting_nondeterministic_payment_bugs_in_Ethereum_smart_contracts/figures?lo1智能合约是区块链技术的核心。我们可以根据以下公式定义智能合约智能合约事务处理和保存机制完备的状态机智能合约…