先序二叉树的线索化,并找指定结点的先序后继

#include<stdio.h>
#include<stdlib.h>
#define elemType char
//线索二叉树结点 
typedef struct ThreadNode{
    elemType data;
    struct ThreadNode *lchild,*rchild;
    int ltag,rtag;//用来判断一个结点是否有线索 
}ThreadNode,*ThreadTree;
//全局变量pre,指向当前结点的前驱
ThreadNode* pre=NULL; 
//初始化一颗二叉树 
bool initTree(ThreadNode** root,elemType data){
    *root=(ThreadNode*)malloc(sizeof(ThreadNode));
    if((*root)==NULL){
        return false;
    }
    (*root)->data=data;
    (*root)->lchild=NULL;
    (*root)->rchild=NULL;
    (*root)->ltag=0;
    (*root)->rtag=0;
    return true;
}
//回收动态开辟的内存 
void destroyTree(ThreadNode* root){
    if(root!=NULL){
        if(root->ltag==0){//确保其左孩子不是线索 
            destroyTree(root->lchild);
        }
        if(root->rtag==0){//确保其右孩子不是线索 
            destroyTree(root->rchild);
        }
        free(root);
    }
}
//给指定结点增添左孩子
bool addLeftNode(ThreadNode* curRoot,elemType data){
    ThreadNode* addNode=(ThreadNode*)malloc(sizeof(ThreadNode));
    if(addNode==NULL){
        return false;
    }
    addNode->data=data;
    addNode->lchild=NULL;
    addNode->rchild=NULL;
    addNode->ltag=0;
    addNode->rtag=0;
    curRoot->lchild=addNode;
    return true;
}
//给指定结点增添右孩子
bool addRightNode(ThreadNode* curRoot,elemType data){
    ThreadNode* addNode=(ThreadNode*)malloc(sizeof(ThreadNode));
    if(addNode==NULL){
        return false;
    }
    addNode->data=data;
    addNode->lchild=NULL;
    addNode->rchild=NULL;
    addNode->ltag=0;
    addNode->rtag=0;
    curRoot->rchild=addNode;
    return true;
}
//先序遍历 
void preOrder(ThreadNode* curRoot){
    if(curRoot!=NULL){
        printf("%c ",curRoot->data);
        preOrder(curRoot->lchild);
        preOrder(curRoot->rchild);
    }
}
void visit(ThreadNode* p){
    if(p->lchild==NULL){
        p->lchild=pre;
        p->ltag=1;
    }
    if(pre!=NULL&&pre->rchild==NULL){
        pre->rchild=p;
        pre->rtag=1;
    }
    pre=p;
}
//先序遍历二叉树,一边遍历一边线索化
void preThread(ThreadTree T){
    if(T!=NULL){
        visit(T);//先处理根节点 
        if(T->ltag==0){//确保lchild不是前驱线索,避免出现死循环 
            preThread(T->lchild);
        }
        if(T->rtag==0){
            preThread(T->rchild);            
        }

    }

//先序线索化二叉树
void createPreThread(ThreadTree T){
    pre=NULL;//pre初始化为NULL 
    if(T!=NULL){//非空二叉树才能线索化 
        preThread(T);//先序线索化二叉树 
        if(pre->rchild==NULL){
            pre->rtag=1;//处理遍历最后一个结点 
        }
    }
    
}
//-----------------------------------------在先序线索二叉树中找到指定结点p的先序后继next----------------------------------------
ThreadNode* firstAfterRoot(ThreadNode* p){
    if(p!=NULL){
        if(p->ltag==1){//表明左指针被线索化,没有左子树 
            return p->rchild;
        }
        else{
            return p->lchild;
        }
    }
}
ThreadNode* findPreNext(ThreadNode* p){
    if(p!=NULL){
        if(p->rtag==0) return firstAfterRoot(p);
        else return p->rchild;
    }
}
//-----------------------------------------在先序线索二叉树中找到指定结点p的先序后继next----------------------------------------

//利用先序线索二叉树实现非递归先序遍历
void PreOrder(ThreadNode* root){
    for(ThreadNode* cur=root;cur!=NULL;cur=findPreNext(cur)){
        printf("%c ",cur->data);
    }
}
int main(){
    ThreadTree root;
    initTree(&root,'A');
    addLeftNode(root,'B');
    addRightNode(root,'C');
    addRightNode(root->lchild,'D');
    addLeftNode(root->rchild,'E');
    printf("普通的先序遍历:\n");
    preOrder(root);
    printf("\n");
    
    createPreThread(root);
    printf("非递归的先序遍历:\n");
    PreOrder(root);
    printf("\n");
    destroyTree(root);
    return 0;
}

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

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

相关文章

深入解析 BitBake 日志机制:任务调度、日志记录与调试方法

1. 引言&#xff1a;为什么 BitBake 的日志机制至关重要&#xff1f; BitBake 是 Yocto 项目的核心构建工具&#xff0c;用于解析配方、管理任务依赖&#xff0c;并执行编译和打包任务。在 BitBake 构建过程中&#xff0c;日志记录机制不仅用于跟踪任务执行情况&#xff0c;还…

C++--迭代器(iterator)介绍---主要介绍vector和string中的迭代器

目录 一、迭代器&#xff08;iterator&#xff09;的定义 二、迭代器的类别 三、使用迭代器 3.1 迭代器运算符 3.2 迭代器的简单应用&#xff1a;使用迭代器将string对象的第一个字母改为大写 3.3 将迭代器从一个元素移动到另外一个元素 3.4 迭代器运算 3.5 迭代器的复…

基于multisim的自动干手器设计与仿真

1 设计的任务与要求 设计一个输出 5V 的直流稳压电源。用开关的闭合模拟手挡住光线的功能。用灯的亮灭模拟烘干吹风功能。 2 方案论证与选择 2.1 自动干手器的系统方案 本设计由5V直流电源、红外发射电路、红外接收电路、灯模拟电路构成。 1. 5V直流电源系统 这一部分是整…

【算法学习之路】7.链表算法

链表算法 前言一.原地逆置思路一&#xff1a;头插法思路二&#xff1a;双指针法思路3&#xff1a;递归 例题&#xff1a;1.头插法2.双指针法3&#xff0c;递归 二.双指针快慢指针&#xff1a;一个指针快一个指针慢例题1例题2 前言 我会将一些常用的算法以及对应的题单给写完&am…

分布式锁—7.Curator的分布式锁

大纲 1.Curator的可重入锁的源码 2.Curator的非可重入锁的源码 3.Curator的可重入读写锁的源码 4.Curator的MultiLock源码 5.Curator的Semaphore源码 1.Curator的可重入锁的源码 (1)InterProcessMutex获取分布式锁 (2)InterProcessMutex的初始化 (3)InterProcessMutex.…

IPD(集成产品开发)简介

参考&#xff1a;IPD咨询_研发管理咨询_IPD集成产品开发-百思特管理咨询集团 一、什么是IPD IPD到底是什么&#xff1f;一套体系&#xff1f;一些流程&#xff1f;还是一种模式&#xff1f; 华为在整个企业内部改革中最重要的两个项目一个是ISC(集成供应链)&#xff0c;另外…

解决Jenkins默认终止Shell产生服务进程的问题

1、Windows环境 Jenkins进行Build steps的使用Execute Windows batch command启动微服务&#xff08;Jar包&#xff09;&#xff0c;Jenkins会默认终止Shell产生的服务进程&#xff0c;而在命令行能够正常运行的服务进程。 1.1 使用命令行启动服务是正常 使用命令行执行 正常…

C 语言数据结构(三):栈和队列

目录 1. 栈 1.1 栈的概念及结构 1.2 栈的实现 2. 队列 2.1 队列的概念及结构 2.2 队列的实现 &#x1f4ac; &#xff1a;如果你在阅读过程中有任何疑问或想要进一步探讨的内容&#xff0c;欢迎在评论区畅所欲言&#xff01;我们一起学习、共同成长~&#xff01; &#x…

多模态分子预训练模型 - SPMM 评测

SPMM 是 Structure-Property Multi-Modal foundation model 的简称&#xff0c;一种多模态分子性质-结构双向预训练模型。作者是韩国科学技术研究院人工智能研究生院&#xff0c;大田&#xff0c;韩国的 Jong Chul Ye&#xff0c;于 2024 年 3 月 14 日 发表在 nature communic…

算法.习题篇

算法 — 地大复试 模拟 while循环和MOD循环计数 1.约瑟夫问题 http://bailian.openjudge.cn/practice/3254 using namespace std;bool isNoPeople(vector<bool> c)//判断当前数组是否一个小孩都没有了 {bool nopeople true;for (bool ival : c){if ( ival true)nop…

C++第十节:map和set的介绍与使用

【本节要点】 1.关联式容器2.键值对3.map介绍与使用4.set介绍与使用5.multimap与multisedd的介绍与使用 一、关联式容器&#xff1a;数据管理的核心利器 关联式容器是STL中用于高效存储和检索键值对&#xff08;key-value pair&#xff09;的数据结构&#xff0c;其底层基于红黑…

Java 大视界 -- Java 大数据在智能家居能源管理与节能优化中的应用(120)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

DeepSeek-R1本地化部署(Mac)

一、下载 Ollama 本地化部署需要用到 Ollama&#xff0c;它能支持很多大模型。官方网站&#xff1a;https://ollama.com/ 点击 Download 即可&#xff0c;支持macOS,Linux 和 Windows&#xff1b;我下载的是 mac 版本&#xff0c;要求macOS 11 Big Sur or later&#xff0c;Ol…

手写简易Tomcat核心实现:深入理解Servlet容器原理

目录 一、Tomcat概况 1. tomcat全局图 2.项目结构概览 二、实现步骤详解 2.1 基础工具包&#xff08;com.qcby.util&#xff09; 2.1.1 ResponseUtil&#xff1a;HTTP响应生成工具 2.1.2 SearchClassUtil&#xff1a;类扫描工具 2.1.3 WebServlet&#xff1a;自定义注解…

OpenHarmony子系统开发编译构建指导

OpenHarmony子系统开发编译构建指导 概述 OpenHarmony编译子系统是以GN和Ninja构建为基座&#xff0c;对构建和配置粒度进行部件化抽象、对内建模块进行功能增强、对业务模块进行功能扩展的系统&#xff0c;该系统提供以下基本功能&#xff1a; 以部件为最小粒度拼装产品和独…

红日靶场(一)——个人笔记

说明&#xff1a; 红日靶场官网 http://vulnstack.qiyuanxuetang.net/vuln/detail/2/ 靶场默认密码 hongrisec2019 预留空间 【攻击机Kail_2023.3】70G 【靶场win7】32G 【靶场Win2K3 】11G 【靶场winserver08】23G 环境搭建 修改VMnet1、VMnet2网卡的地址 将VMnet1作为内…

网络基础(一)【网络发展/认识协议/网络 VS 系统/以太网通信原理/重谈协议/网络中的地址管理】

网络基础&#xff08;一&#xff09; 1. 网络的发展2. 认识协议3. 网络 VS 系统4. 以太网通信原理5. 重谈协议6. 网络中的地址管理 1. 网络的发展 最开始时&#xff0c;计算机之间相互独立。 但是为了协作完成一些任务&#xff0c;就产生了计算机之间相互通讯的需求&#xff0c…

【ESP-IDF】组件

前言 对于要封装自己的库&#xff0c;在ESP-IDF中&#xff0c;可以采用构建组件的方式导入&#xff0c;而不是单纯在文件夹下导入.h和.c文件&#xff0c;不然一旦要导入的文件过多&#xff0c;它们背后的依赖可能就会相互交叉&#xff0c;不在方便移除和复用。本文就分别讲述&a…

AR配置静态IP双链路负载分担示例

AR配置静态IP双链路负载分担示例 适用于大部分企业网络出口 业务需求&#xff1a; 运营商1分配的接口IP为100.100.1.2&#xff0c;子网掩码为255.255.255.252&#xff0c;网关IP为100.100.1.1。 运营商2分配的接口IP为200.200.1.2&#xff0c;子网掩码为255.255.255.248&am…

视觉 Yolov11 环境配置(GPU版)

虚拟环境 首先用 anaconda 创建虚拟环境 根据自己需求创建一个虚拟环境 一个环境名叫 yolov11-py-3-8 就创建好了&#xff0c;后续的 yolov11 就会以这个环境去做深度学习&#xff08;这里不建议把环境的 py 版本设置到最新&#xff0c;设置个 3.8 或者 3.10 完全够用了 &am…