线索二叉树(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;	//	右指针域 
	flag ltag,rtag;			//	flag == 0——指向左、右孩子,flag == 1——指向前驱、后继结点
	
}ThreadTNode,*ThreadBiTree;

void Creat_BiTree(ThreadBiTree * T);						// 建立二叉树 
void Creat_PreThreadBiTree(ThreadBiTree * T);				// 建立先序线索二叉树 
void PreThread_BiTree(ThreadBiTree * T, ThreadBiTree * pre);// 先序遍历线索化二叉树 
ThreadBiTree Get_Next(ThreadBiTree T);						// 获取先序线索二叉树的后继结点 
void PreTraverse_ThreadBiTree(ThreadBiTree T);				// 先序遍历线索二叉树 
bool Destroy_PreThreadBiTree(ThreadBiTree T);				// 销毁线索二叉树 


int main()
{
	ThreadBiTree T;
	printf("请输入根结点:");
	Creat_BiTree(&T);
	Creat_PreThreadBiTree(&T);
	printf("\n");
	printf("先序遍历输出线索二叉树:");
	PreTraverse_ThreadBiTree(T);
	printf("\n");
	if(Destroy_PreThreadBiTree(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);
	}
}

void Creat_PreThreadBiTree(ThreadBiTree * T)
{
	ThreadBiTree pre = NULL;
	
	if(!(*T))
		return;
	else
	{
		PreThread_BiTree(T, &pre);
		pre->rtag = 1;
		pre->rchild = NULL;
		return;
	}	 
} 

void PreThread_BiTree(ThreadBiTree * T, ThreadBiTree * pre)
{
	if(!(*T))
		return;
	
	if((*T)->lchild == NULL)
	{
		(*T)->ltag = Thread;
		(*T)->lchild = *pre;
	}
	if((*pre) != NULL && (*pre)->rchild == NULL )	//	注意这两玩意的顺序哈 
	{
		(*pre)->rtag = Thread;
		(*pre)->rchild = *T;
	}	
	*pre = *T;							 //	更新指向前趋结点的指针 
	if((*T)->ltag == Link)
	PreThread_BiTree(&(*T)->lchild, pre);//	递归线索化左子树 
	/*
		在前面判断左孩子是否为空的时候,假设左孩子为空,这时已经改变了左孩子指针域的值,
		因为左孩子为空,这时再对其进行递归遍历则毫无意义,进行递归遍历的前提是左孩子必须存在,
		否则会出现段错误 
	*/
	PreThread_BiTree(&(*T)->rchild, pre);//	递归线索化右子树 
}

ThreadBiTree Get_Next(ThreadBiTree T)	//	寻找下一个结点 
{
	if(!T)
		return NULL;
	else
	{
		if(T->rtag == Thread || T->ltag == Thread)
			return T->rchild;
		else
			return T->lchild;
		
	/*	
		if(T->rtag == Thread)	该结点为左孩子结点 
			return T->rchild;
		else
		{
			if(T->ltag == Link)	该结点为根结点 
				return T->Lchild;
			else
				return T->rchild;
		}
	*/	
		
	}
}

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

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

 

猜你喜欢

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