后序线索化二叉树,并找到指定结点前驱,非递归逆序输出

#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 postOrder(ThreadNode* curRoot){

if(curRoot!=NULL){

postOrder(curRoot->lchild);

postOrder(curRoot->rchild);

printf("%c ",curRoot->data);

}

}

void visit(ThreadNode* q){

if(q->lchild==NULL){//左子树为空,建立前驱线索

q->lchild=pre;

q->ltag=1;

}

if(pre!=NULL&&pre->rchild==NULL){

pre->rchild=q;

pre->rtag=1;

}

pre=q;

}

//后序遍历二叉树,一边遍历,一边线索化

void postThread(ThreadTree T){

if(T!=NULL){

postThread(T->lchild);//后序遍历左子树

postThread(T->rchild);//后序遍历右子树

visit(T);//线索化根节点

}

}

//后序线索化二叉树T

void createPostThread(ThreadTree T){

pre=NULL;//pre初始化为NULL

if(T!=NULL){//非空二叉树才能线索化

postThread(T);//后序线索化二叉树

if(pre->rchild==NULL){

pre->rtag=1;//处理最后一个结点

}

}

}

ThreadNode* lastBefoRoot(ThreadNode* curRoot){

if(curRoot->rtag==1){//表示右孩子被线索化,没有右孩子

return curRoot->lchild;

}

else return curRoot->rchild;

}

//根据后序线索二叉树找到指定结点的前驱结点

ThreadNode* findBefore(ThreadNode* root){

if(root!=NULL){

if(root->ltag==0) return lastBefoRoot(root);

else return root->lchild;

}

}

//利用后序线索二叉树,逆序输出,非递归

void RevPostOrder(ThreadNode* root){

for(ThreadNode* cur=root;cur!=NULL;cur=findBefore(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");

postOrder(root);

printf("\n");

createPostThread(root);

printf("利用后序线索二叉树逆序输出:\n");

RevPostOrder(root);

printf("\n");

destroyTree(root);

return 0;

}

相关推荐
BothSavage18 小时前
Trae远程开发中DeepSeek自定义模型4054错误的排查与修复
算法
小林ixn18 小时前
从暴力到KMP:一道题彻底搞懂字符串匹配的前世今生
算法
烬羽19 小时前
字符串算法入门:从反转字符串到回文判断,面试不再慌
算法·面试
先吃饱再说1 天前
判断回文字符串,从一行代码到双指针优化
算法
黄敬峰2 天前
深入理解算法核心:从递归思想、数组扁平化到快速排序
算法
得物技术2 天前
从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理
人工智能·算法·架构
AI小老六2 天前
SkillOpt 架构拆解:把 Skill 文本当参数,用执行轨迹训练 Agent
后端·算法·ai编程
胡萝卜术2 天前
从“分数打架”到“排名投票”:为什么你的ChatBI必须用RRF?
算法·设计模式·面试
Asize2 天前
初识DFS 与 BFS:递归、队列与图遍历
算法