当前位置:网站首页>先序线索二叉树
先序线索二叉树
2022-06-25 22:02:00 【乖乖怪123】
参照 中序线索二叉树
整体思路和中序线索二叉树差不多
如何在先序线索二叉树中找到结点的后继?
结点p的后继:
- p有左孩子,即p->ltag==0,则左孩子即为后继
- p无左孩子,则右指针rchild即为p在先序下的后继结点,
prchild要么指向右孩子(右孩子其实也是在先序下的后继结点),要么指向p在先序 下的后继结点
只是在先序线索void PreThread(ThreadTree &p,ThreadTree &pre)要注意添加tag的判断,不然可能会出现死循环,如下代码段所示
if(p->ltag != 1)//@@@ 这里因为p->lchild可能是p的前驱结点,//如果不判断ltag,则会死循环,
PreThread(p->lchild,pre);//递归,线索化左子树
if(p->rtag != 1)//@@@
PreThread(p->rchild, pre);//递归,线索化右子树
完整测试代码
//先序线索二叉树
#include<stdio.h>
#include<stdlib.h>
#define ElemType char
//tag为0表示指向左/右孩子,为1表示指向结点的前驱/后继
typedef struct ThreadNode{
ElemType data;//数据元素
struct ThreadNode *lchild,*rchild;//左右孩子指针
int ltag;//因为定义结构体时,并未给其分配内存,所以初值是无法存储的。应该声明结构体变量后,手工赋值
int rtag;//左右线索标记
}ThreadNode,*ThreadTree;
void visit(ThreadTree T){
printf("%c ",T->data);
}
//先序线索二叉树的构造, 根左右
void PreThread(ThreadTree &p,ThreadTree &pre){
if(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;//标记当前结点成为刚刚访问过的结点
if(p->ltag != 1)//@@@ 这里因为p->lchild可能是p的前驱结点,
//如果不判断ltag,则会死循环,
PreThread(p->lchild,pre);//递归,线索化左子树
if(p->rtag != 1)//@@@
PreThread(p->rchild, pre);//递归,线索化右子树
}//if(p != NULL)
}
//通过先序遍历建立先序线索二叉树的主过程算法如下:
void CreatePreThread(ThreadTree &T){
ThreadTree pre=NULL;
if(T){
//非空二叉树,线索化
PreThread(T,pre);//线索化二叉树
pre->rchild==NULL;//处理遍历的最后一个结点
pre->rtag=1;
//printf("CreatePreThread Finished\n");
}
}
//求先序线索二叉树中,先序序列下的第一个结点
ThreadNode *Firstnode(ThreadNode *p){
return p;
}
//求先序线索二叉树中,结点p在先序序列下的后继
/*p的后继: 1. p有左孩子,即p->ltag==0,则左孩子即为后继 2. p无左孩子,则右指针rchild即为p在先序下的后继结点, prchild要么指向右孩子(右孩子其实也是在先序下的后继结点),要么指向p在先序下的后继结点 */
ThreadNode *Nextnode(ThreadNode *p){
if(p->ltag==0){
//左孩子指针
return Firstnode(p->lchild);
}
else{
// ltag==1 直接返回后继线索
return p->rchild;
}
}
//利用上面的两个算法,
//可以写出不含头结点的先序线索二叉树的先序遍历算法
void Preorder(ThreadNode *T){
for(ThreadNode *p=Firstnode(T);p!=NULL;p=Nextnode(p)){
visit(p);
}
}
//创建线索二叉树,按前序输入, #表示空节点
bool CreateThreadTree(ThreadTree &T){
ElemType ch;
scanf("%c", &ch);
if(ch == '#'){
//printf("您要创建一棵空树吗?\n");
T=NULL;
return false;
}
else{
T=(ThreadTree)malloc(sizeof(ThreadNode));
T->ltag=T->rtag=0;
if(!T){
printf("malloc failure\n");
return false;
}
T->data = ch;
CreateThreadTree(T->lchild);
CreateThreadTree(T->rchild);
return true;
}
}
//后序销毁
bool DestroyThreadTree(ThreadTree T){
if(T==NULL){
printf("空节点\n");
return false;
}
if(T->ltag!=1)//@@@
DestroyThreadTree(T->lchild);
if(T->rtag!=1)//@@@
DestroyThreadTree(T->rchild);
printf("销毁%c\n",T->data);
free(T);//@@@'
T=NULL;
return true;
}
//先序递归遍历线索二叉树
void PreOrder(ThreadTree T){
if(T){
visit(T);
if(T->ltag!=1)
PreOrder(T->lchild);
if(T->rtag != 1)
PreOrder(T->rchild);
}
}
int main(){
ThreadTree T=NULL;
printf("按前序输入二叉树中节点的值(输入#表示空节点)\n");
CreateThreadTree(T);//输入前序,建立二叉树
CreatePreThread(T);//通过先序遍历建立先序线索二叉树
ThreadNode *p=Firstnode(T);//求先序遍历下的第一个结点
printf("\n先序遍历的第一个结点p: %c\n",p->data);
ThreadNode* r=Nextnode(p);//求中序遍历下p的后继
printf("p的后继r: %c\n",r->data);
printf("先序遍历线索二叉树(递归PreOrder ≈ 正常BinaryTree遍历): \n");
PreOrder(T);
printf("\n");
printf("\n先序遍历线索二叉树(非递归Preorder ≈ Firstnode+Nextnode): \n");
Preorder(T);
printf("\n用完要记得销毁哦!\n");
DestroyThreadTree(T);
return 0;
}
测试样例:

测试结果
边栏推荐
- User interaction scanner usage Advanced Edition example
- Pointer strengthening and improvement
- Leetcode (435) - no overlapping interval
- 【无标题】打开一个项目连接,无法正常显示时,ping一下ip
- After xampp restarts, the MySQL service cannot be started.
- Repoptimizer: it's actually repvgg2
- The first public available pytorch version alphafold2 is reproduced, and Columbia University is open source openfold, with more than 1000 stars
- 记一次beego通过go get命令后找不到bee.exe的坑
- Summary of common JDBC exceptions and error solutions
- 谷歌浏览器(Chrome)最新v80版本下载
猜你喜欢

提取系统apk

RepOptimizer: 其实是RepVGG2

#23class介绍

28 rounds of interviews with 10 companies in two and a half years (including byte, pinduoduo, meituan, Didi...)

Hibernate architecture introduction and environment construction (very detailed)

软件测试面试一直挂,面试官总是说逻辑思维混乱,怎么办?

LeetCode-1528-重新排列字符串-哈希表-字符串

Hibernate entity class curd, transaction operation summary

character string

UE4 学习记录一 创建角色,并控制其移动
随机推荐
String object (constant) pool
How to add cartoon characters to the blog park?
Download the latest V80 version of Google Chrome
hiberate核心API/配置文件/一级缓存详解
LeetCode-1528-重新排列字符串-哈希表-字符串
[Axi] interpretation of Axi protocol disorder mechanism
做接口测试,这3种工具到底什么时候用?
期末复习【机器学习】
Analysis and comprehensive summary of full type equivalent judgment in go
Ad20 learning notes I
软件测试面试一直挂,面试官总是说逻辑思维混乱,怎么办?
头歌 第3关:使用线程锁(Lock)实现线程同步
Technology blog site collection
CSDN add on page Jump and off page specified paragraph jump
QComboBox下拉菜单中有分隔符Separator时的样式设置
转载: QTableWidget详解(样式、右键菜单、表头塌陷、多选等)
[Axi] interpretation of Axi protocol atomic access
库项目和App项目中清单文件的包名不要相同
CSDN force value
Konva series tutorial 2: drawing graphics