C语言实现线索二叉树

学数据结构的时候没有学线索二叉树,现在考研需要,补上了。
线索二叉树中给每个节点加上标记,使叶节点的空的数据域填上前驱或者后继,使得线索二叉树能快速的找到前驱后继
在这里插入图片描述

中序线索二叉树

在这里插入图片描述
线索化时如节点左子树为空,则添加前驱;设置全局变量pre,保存上一个访问的节点,访问下一个节点时,如果pre右子树为空,则pre的后继连上此节点。

#include<stdio.h>
#include<stdlib.h>
#define N 100
typedef int ElemType;
typedef struct ThreadNode{
	ElemType data;
	struct ThreadNode *lchild,*rchild;
	int ltag,rtag;		//左右线索 
}ThreadNode,*ThreadTree;
ThreadNode *pre=NULL;
void visit(ThreadNode *q){			
	if(q->lchild==NULL){
		q->lchild=pre;
		q->ltag=1;
	}
	if(pre&&pre->rchild==NULL){
		pre->rchild=q;
		pre->rtag=1;
	}
	pre=q;
}
void InThread(ThreadTree T){		//边遍历边线索化 
	if(T){
		InThread(T->lchild);
		visit(T);				//后序调一下位置即可 
		InThread(T->rchild);
	}
}
void CreatInThread(ThreadTree T){	//线索化二叉树 
	pre=NULL;
	if(T){
		InThread(T);
		if(pre->rchild==NULL){		//如果最后一点为空,给他加标记 
			pre->rtag=1;			
		}
	}
}

ThreadNode *Firstnode(ThreadNode *p){			//p的第一个被中序遍历的节点 
	while(p->ltag==0) p=p->lchild;
	return p;
}
ThreadNode *Nextnode(ThreadNode *p){			//中序线索二叉树中p的后继 
	if(p->rtag==0) return Firstnode(p->rchild);
	else return p->rchild;
}
void Inoder(ThreadNode *T){						//非递归中序遍历二叉树 
	ThreadNode *p;
	for(p=Firstnode(T);p!=NULL;p=Nextnode(p)){
		printf("%d ",p->data);
	}
	printf("\n");
}

ThreadNode *Lastnode(ThreadNode *p){			//p的最后一个被中序遍历的节点 
	while(p->rtag==0) p=p->rchild;
	return p;
}
ThreadNode *Prenode(ThreadNode *p){				//中序线索二叉树中p的前继 
	if(p->ltag==0) return Lastnode(p->lchild);
	else return p->lchild;
}
void RevInoder(ThreadNode *T){					//非递归逆向中序遍历二叉树 
	ThreadNode *p;
	for(p=Lastnode(T);p!=NULL;p=Prenode(p)){
		printf("%d ",p->data);
	}
	printf("\n");
}

ThreadTree Creat(ThreadTree T,int x){
	if(!T){
		ThreadTree T=(ThreadTree)malloc(sizeof(ThreadNode));
		T->data=x;
		T->lchild=T->rchild=NULL;
		T->ltag=T->rtag=0;
	}
	else {
		if(x>T->data){
			T->rchild=Creat(T->rchild,x);
		}
		else{
			T->lchild=Creat(T->lchild,x);
		}
	}
}
int main()
{
	int i,j,k;
	int a[10]={2,5,6,9,3,4,7,8,1,0};
	ThreadTree T;
	for(i=0;i<9;i++){
		T=Creat(T,a[i]);		
	}
	CreatInThread(T);
	Inoder(T);
	RevInoder(T); 
	return 0;
}

先序线索二叉树

先序线索二叉树实现同中序基本一致,要注意的点是左边节点的数据可能是线索并不是真正的左子树,所以在遍历的时候加上一个判断条件。
在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
#define N 100
typedef int ElemType;
typedef struct ThreadNode{
	ElemType data;
	struct ThreadNode *lchild,*rchild;
	int ltag,rtag;		//左右线索 
}ThreadNode,*ThreadTree;
ThreadNode *pre=NULL;
void visit(ThreadNode *q){			
	if(q->lchild==NULL){
		q->lchild=pre;
		q->ltag=1;
	}
	if(pre&&pre->rchild==NULL){
		pre->rchild=q;
		pre->rtag=1;
	}
	pre=q;
}
void PreThread(ThreadTree T){		//边遍历边线索化 
	if(T){
		visit(T);
		if(T->ltag==0){				//防止左边为线索无限循环的问题 
			PreThread(T->lchild);		
		}
		PreThread(T->rchild);
	}
}
void CreatPreThread(ThreadTree T){	//线索化二叉树 
	pre=NULL;
	if(T){
		PreThread(T);
		if(pre->rchild==NULL){		//如果最后一点为空,给他加标记 
			pre->rtag=1;			
		}
	}
}
ThreadTree Creat(ThreadTree T,int x){
	if(!T){
		ThreadTree T=(ThreadTree)malloc(sizeof(ThreadNode));
		T->data=x;
		T->lchild=T->rchild=NULL;
	}
	else {
		if(x>T->data){
			T->rchild=Creat(T->rchild,x);
		}
		else{
			T->lchild=Creat(T->lchild,x);
		}
	}
}

ThreadNode *NextNode(ThreadNode *p){			//先序二叉树的后继 
	if(p->rtag==1) return p->rchild;
	else {
		if(p->lchild) return p->lchild;
		else return p->rchild;
	}
}
int main()
{
	int i,j,k;
	int a[10]={2,5,6,9,3,4,7,8,1,0};
	ThreadTree T=(ThreadTree)malloc(sizeof(ThreadNode));
	T->data=a[0];
	T->lchild=T->rchild=NULL;
	for(i=1;i<9;i++){
		T=Creat(T,a[i]);		
	}
	CreatPreThread(T);
	printf("%d",NextNode(T)->data);
	return 0;
}

后序线索二叉树

后序线索二叉树同中序线索二叉树实现基本一致,遍历的时候调一下顺序就可。

#include<stdio.h>
#include<stdlib.h>
#define N 100
typedef int ElemType;
typedef struct ThreadNode{
	ElemType data;
	struct ThreadNode *lchild,*rchild;
	int ltag,rtag;		//左右线索 
}ThreadNode,*ThreadTree;
ThreadNode *pre=NULL;
void visit(ThreadNode *q){			
	if(q->lchild==NULL){
		q->lchild=pre;
		q->ltag=1;
	}
	if(pre&&pre->rchild==NULL){
		pre->rchild=q;
		pre->rtag=1;
	}
	pre=q;
}
void PostThread(ThreadTree T){		//边遍历边线索化 
	if(T){
		visit(T);
		if(T->ltag==0){				//防止左边为线索无限循环的问题 
			PostThread(T->lchild);		
		}
		PostThread(T->rchild);
	}
}
void CreatPostThread(ThreadTree T){	//线索化二叉树 
	pre=NULL;
	if(T){
		PostThread(T);
		if(pre->rchild==NULL){		//如果最后一点为空,给他加标记 
			pre->rtag=1;			
		}
	}
}
ThreadTree Creat(ThreadTree T,int x){
	if(!T){
		ThreadTree T=(ThreadTree)malloc(sizeof(ThreadNode));
		T->data=x;
		T->lchild=T->rchild=NULL;
	}
	else {
		if(x>T->data){
			T->rchild=Creat(T->rchild,x);
		}
		else{
			T->lchild=Creat(T->lchild,x);
		}
	}
}
ThreadNode *PreNode(ThreadNode *p){
	if(p->ltag==1) return p->lchild;
	else {
		if(p->rchild) return p->rchild;
		else return p->lchild;
	}
}
int main()
{
	int i,j,k;
	int a[10]={2,5,6,9,3,4,7,8,1,0};
	ThreadTree T=(ThreadTree)malloc(sizeof(ThreadNode));
	T->data=a[0];
	T->lchild=T->rchild=NULL;
	for(i=1;i<9;i++){
		T=Creat(T,a[i]);		
	}
	CreatPostThread(T);
	printf("%d",PreNode(T)->data);
	return 0;
}
  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以回答这个问题。线索二叉树遍历分为前序遍历、中序遍历和后序遍历三种。其中,中序遍历是线索二叉树最常用的遍历方法。 实现中序遍历线索二叉树的步骤如下: 1. 首先,需要定义线索二叉树节点的数据结构,包括左子树指针、右子树指针、左子树线索、右子树线索和节点值等信息。 typedef struct ThreadedNode{ char data; struct ThreadedNode *left,*right; int ltag,rtag; }ThreadedNode,*ThreadedTree; 2. 然后,利用前序遍历构建线索二叉树。 void CreateThreadedTree(ThreadedTree &T){ char c; scanf("%c",&c); if(c == '#') T = NULL; else{ T = (ThreadedNode*)malloc(sizeof(ThreadedNode)); T -> data = c; T -> ltag = T -> rtag = 0; CreateThreadedTree(T -> left); CreateThreadedTree(T -> right); } } 3. 接下来,对于中序遍历线索二叉树,需要先中序遍历构建左子树线索。 void InThread(ThreadedNode *p,ThreadedNode *&pre){ if(p!=NULL){ InThread(p->left,pre); if(p->left == NULL){ p->ltag = 1; p->left = pre; } if(pre!=NULL && pre->right == NULL){ pre->rtag = 1; pre->right = p; } pre = p; InThread(p->right,pre); } } 4. 最后,中序遍历线索化整棵树,完成线索二叉树的转换。 void InOrder(ThreadedNode *T){ ThreadedNode *p=T; while(p->ltag == 0) p = p->left; while(p!=NULL){ printf("%c",p->data); if(p->rtag) p=p->right; else p=p->right; while(p!=NULL && p -> ltag == 0) p = p -> left; } } 以上就是用C语言实现线索二叉树的中序遍历代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值