线索二叉树(C语言实现)——后续线索链表

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef char DataType;

//	标志域利用枚举常量来实现 
typedef enum
{
	Link,		//	Link(0)—指针
	Thread		//	Thread(1)—线索 
}flag;

typedef struct TNode
{
	DataType data;				//	数据域 
	struct TNode * lchild;		//	左孩子指针域 
	struct TNode * rchild;		//	右孩子指针域 
	struct TNode * parent;		//	双亲指针域 
	flag ltag,rtag;				//	flag==0 —指向左、右孩子,flag==1 —指向前驱、后继结点
	
}ThreadTNode,*ThreadBiTree;

void Creat_BiTree(ThreadBiTree * T);						//	建立二叉树 
void Creat_PostThreadBiTree(ThreadBiTree * T);				//	建立后序线索二叉树 
void PostThread_BiTree(ThreadBiTree * T, ThreadBiTree * pre);//	后序线索化二叉树 
ThreadBiTree Get_First(ThreadBiTree T);						//	获取线索二叉树中的第一个结点
ThreadBiTree Get_Next(ThreadBiTree T);						//	获取线索二叉树的后继结点 
void PostTraverse_ThreadBiTree(ThreadBiTree T);				//	后序遍历线索二叉树 
bool Destroy_PostThreadBiTree(ThreadBiTree T);				//	销毁线索二叉树 


int main()
{
	ThreadBiTree T;
	printf("请输入根结点:");
	Creat_BiTree(&T);
	Creat_PostThreadBiTree(&T);
	printf("\n");
	printf("后序遍历输出线索二叉树:");
	PostTraverse_ThreadBiTree(T);
	printf("\n");
	if(Destroy_PostThreadBiTree(T))
		printf("销毁成功!\n");
	else
		printf("销毁失败!\n");

	return 0;
}

void Creat_BiTree(ThreadBiTree * T)
{
	char ch;
	fflush(stdin);
	scanf("%c",&ch);
	if(ch == '#')
	{
		*T = NULL;
		return;
	}
	else
	{
		*T = (ThreadBiTree)malloc(sizeof(ThreadTNode));
		(*T)->data = ch;
		printf("请输入%c的左孩子:",ch);
		Creat_BiTree(&(*T)->lchild);
		printf("请输入%c的右孩子:",ch);
		Creat_BiTree(&(*T)->rchild);
		if((*T)->lchild)
			(*T)->lchild->parent = *T;
		if((*T)->rchild)
			(*T)->rchild->parent = *T;
	}
}

void Creat_PostThreadBiTree(ThreadBiTree * T)
{
	ThreadBiTree pre = NULL;
	
	if(!(*T))
		return;
	else
	{
		PostThread_BiTree(T, &pre);
	/*	pre->rtag = 1;
		pre->rchild = NULL;
		
		后序遍历:最后一个结点指向根结点,所以不用修改最后一个结点
				  的右标志域和右指针域的指向, 
	*/	return;
	}	 
} 

void PostThread_BiTree(ThreadBiTree * T, ThreadBiTree * pre)
{
	if(!(*T))
		return;
		
	PostThread_BiTree(&(*T)->lchild, pre);//	递归线索化左子树 
	PostThread_BiTree(&(*T)->rchild, pre);//	递归线索化右子树 
	
	if((*T)->lchild == NULL)
	{
		(*T)->ltag = Thread;
		(*T)->lchild = *pre;
	}
	if((*pre) != NULL && (*pre)->rchild == NULL )	//	注意这两玩意的顺序哈
	{
		(*pre)->rtag = Thread;
		(*pre)->rchild = *T;
	}	
	*pre = *T;								 //	更新指向前趋结点的指针 
}

ThreadBiTree Get_First(ThreadBiTree T)
{
	while(T->ltag == Link)
		T = T->lchild;
		
	if(T->rtag == Link)
		return Get_First(T->rchild);
		
	return T; 
	
/*
 寻找第一个结点:
		1.找到最左边的结点
		2.判断这个结点是否有右孩子,如果有的话,
		  继续寻找以右孩子为根结点的子树的最左边的结点, 
		  如果没有,则最左边的结点就是第一个结点		 
	
*/
} 

ThreadBiTree Get_Next(ThreadBiTree T)	//	寻找下一个结点 
{
	if(T->rtag == Thread)
		return T->rchild;
	else
	{
	//	如果是根结点 
		if(T->parent == NULL)
			return NULL;
	//	如果是右孩子
		else if(T->parent->rchild == T)
			return  T->parent;
	//	如果是左孩子 
		else
		{
			if(T->parent->rtag == Thread)
				return T->parent;
			else
				return Get_First(T->parent->rchild);
		} 
	} 

/*
  寻找后继结点:
		1.是根结点:Next == NULL;
		2.是左孩子:那么判断双亲右子树是否为空,如果为空,Next == Parent
					如果不空,Next == Get_First(T->parent->rchild)
		3.是右孩子:Next == Parent 
*/
}

void PostTraverse_ThreadBiTree(ThreadBiTree T)
{	
	ThreadBiTree p = Get_First(T);	//	获取后序线索二叉树的第一个结点 
	while(p)
	{
		printf("%3c",p->data);		//	后序遍历输出前序线索二叉树 
		p = Get_Next(p);
	} 
	
	return;
}

bool Destroy_PostThreadBiTree(ThreadBiTree T)
{
	ThreadBiTree p = Get_First(T);
	while(p)
	{
		ThreadBiTree q = Get_Next(p);
		free(p);
		p = q;
	}
	
	T = p = NULL;
	return true;
}

 

 

猜你喜欢

转载自blog.csdn.net/Mr_Morgans/article/details/121153071