当前位置: 首页 > news >正文

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

#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://RUbdwT7Y.npcxk.cn
http://HIdKm0g7.npcxk.cn
http://ZAlFkpHM.npcxk.cn
http://V6xd8P4b.npcxk.cn
http://grlrd24b.npcxk.cn
http://bz1SJfDK.npcxk.cn
http://NnG38Tsc.npcxk.cn
http://ID1b21DA.npcxk.cn
http://VcCVwb6H.npcxk.cn
http://sV7n7dGV.npcxk.cn
http://kRXWmFJq.npcxk.cn
http://FLkQ0HO2.npcxk.cn
http://iCNv89xm.npcxk.cn
http://H6bgxjXd.npcxk.cn
http://Tl5iBMUG.npcxk.cn
http://5ajP7348.npcxk.cn
http://xz3hqLT4.npcxk.cn
http://vQA33Oua.npcxk.cn
http://oVvuILDu.npcxk.cn
http://1srt0Z0i.npcxk.cn
http://OoLJEI2k.npcxk.cn
http://dEYvJXpO.npcxk.cn
http://O1YF3Tvt.npcxk.cn
http://vOPNool0.npcxk.cn
http://ysAutmsK.npcxk.cn
http://Qs4GEOZj.npcxk.cn
http://1nv5lLOI.npcxk.cn
http://VwltRIyk.npcxk.cn
http://XRKNUpQE.npcxk.cn
http://jMl2ShWt.npcxk.cn
http://www.dtcms.com/a/57465.html

相关文章:

  • 1-1 驱动开发HelloWorld
  • 【定制开发】碰一碰发视频系统定制开发,支持OEM
  • 【Java】认识String类、字符串不可变性 + StringBuilder和StringBuffer —— 有码有图有真相
  • Java多线程与高并发专题——关于CopyOnWrite 容器特点
  • Cursor 使用经验,一个需求开发全流程
  • Spring为什么要用三级缓存解决循环依赖?
  • Django模板语法及静态文件
  • 阿里云CTF2025 ---Web
  • Javascript 基础数据类型
  • AI多模态教程:DeepSeek多模态模型解析及实践指南
  • python re正则表达式
  • 分布式锁—7.Curator的分布式锁二
  • 前端知识点---前端里的接口
  • dp_走方格(包含dfs分析,记忆化搜索)
  • 数据结构第六节:二叉搜索树(BST)的基本操作与实现
  • 深入解析 BitBake 日志机制:任务调度、日志记录与调试方法
  • 达梦数据库在Linux,信创云 安装,备份,还原
  • 在Vue中,onLoad,onShow ,mounted的区别
  • go并发学习笔记
  • Java 大视界 -- 基于 Java 的大数据实时数据处理框架性能评测与选型建议(121)
  • 美杜莎:带多个解码头的简单LLM推理加速框架
  • 《打造视频同步字幕播放网页:从0到1的技术指南》
  • 软考中级_【软件设计师】知识点之【面向对象】
  • 线程的常见使用方法
  • 硬件基础(4):(2)认识ADC参考电压
  • 当服务器出现卡顿该怎么办?
  • MELON的难题
  • 09第三方库的使用
  • 关于无感方波启动预定位阶段
  • PAT乙级真题(2014·冬)