线索二叉树

#include 
#include 

typedef enum{Link,Thread} PointerTag;  

typedef struct ThrBiTreeNode{  //树的节点
	char data;
	struct ThrBiTreeNode *lchild,*rchild;
	PointerTag ltag,rtag;  //枚举类型变量,用于线索二叉树中,指示左右孩纸指针lchild,rchild的意义:指向其孩纸or后继
} ThrBiTreeNode,*ThrBiTree;

ThrBiTree pre,p;  //全局变量,pre为树的头,若树不为空,pre->lchild指向树的跟节点,pre->rchild指向中序遍历的起始节点

void CreateThrBiTree(ThrBiTree *T)  //先序(根节点-左子树-右子树)创建线索二叉树
{
	if(!T)  return;
	char c;
	scanf("%c",&c);
	if(c==' ')
		(*T)=NULL;  //没有孩纸的节点的lchild或rchild为NULL
	else
	{
		(*T)=(ThrBiTree)malloc(sizeof(ThrBiTree));
		if(!(*T))  return;
		(*T)->data=c;
		(*T)->ltag=Link;
		(*T)->rtag=Link;  //创建线索二叉树时,所有节点的lchild,rchild都指向其孩纸,没有孩纸的为NULL
		CreateThrBiTree(&(*T)->lchild);
		CreateThrBiTree(&(*T)->rchild);
	}
}

void InOrderTraversing(ThrBiTree T)
{
	if(!T) return;
	InOrderTraversing(T->lchild);
	if(!T->lchild)
	{
		T->ltag=Thread;
		T->lchild=p;
	}
	if(!p->rchild)
	{
		p->rtag=Thread;
		p->rchild=T;
	}
	p=T;
	InOrderTraversing(T->rchild);
}

void InOrderTraverse(ThrBiTree T)  //中序遍历线索二叉树,利用值为NULL的lchild及rchild空间确定(存放)其前驱后继
{
	pre=(ThrBiTree)malloc(sizeof(ThrBiTreeNode));  //pre为ThrBiTree类型指针,不存放数据,是树的头
	if(!pre)  return;
	pre->ltag=Link;
	pre->rtag=Link;
	pre->lchild=pre;
	pre->rchild=pre;  //若树T为空,树头的lchild与rchild都指向梳头自身,可利用if(pre->lchild==pre && pre->rchild==pre)判断树是否为空树
	if(T)
	{
		pre->lchild=T;  //树T不为空,树头的左孩纸指向树根
		pre->rchild=NULL;  //树头的有孩纸是要指向中序遍历的起始节点的,中序遍历前在此处初始化为NULL,用于中序遍历时InOrderTraversing()中第8行的判断
		p=pre;  //p用于记录某个节点的前驱节点
		InOrderTraversing(T);
		if(!p->rchild)  //中序遍历的尾节点指向树的头pre
		{
			p->rchild=pre;
			p->rtag=Thread;
		}
	}
	else
		return;
}

void Print(ThrBiTree pre)  //输出对树中序遍历后的结果
{
	if(!pre)  return;
	ThrBiTreeNode* pt=pre->rchild;
	ThrBiTreeNode* t=(ThrBiTreeNode*)malloc(sizeof(ThrBiTreeNode));
	while(pt!=pre)
	{
		printf("%c",pt->data);
		if(pt->rtag==Thread)  //此处必须作此判断,原因见程序后图2解析
			pt=pt->rchild;
		else  
		{
			t=pt->rchild;
			while(t->ltag==Link)
			{
				t=t->lchild;
			}
			if(t->ltag==Thread && t->lchild==pt)
				pt=t;
		}
	}
}

void main()
{
	ThrBiTree *T=(ThrBiTree*)malloc(sizeof(ThrBiTree));
	CreateThrBiTree(T);
	InOrderTraverse(*T);
	Print(pre);
	free(pre);
	free(T);
}

程序建立的二叉树模型:

线索二叉树_第1张图片

前序创建二叉树时的输入为: ( _ 表示输入为空格)

ABD_H_ _E_ _CF_I_ _GJ_ _ _

中序遍历二叉树顺序为:

DHBEAFICJG

线索二叉树中序遍历的前驱后继表示为:

线索二叉树_第2张图片

////////   pre->ltag==Link,pre->lchild指向根节点A,pre->rtag==Thread,pre->rchild指向中序遍历的起始节点D

如图所示,并不是每一个节点都能通过lchild得到自身的前驱节点,不是每一个结点都能通过rchild得到自身的后继结点。例如:

节点D的后继结点是H,但是D->rtag==Link,所以不能以为D的后继节点就是D->rchild,虽然在本例本树中D的后继结点就是其右孩纸,但直接取后继节点为D->rchild是错误的。所以在Print()函数中需要判断。

你可能感兴趣的:(数据结构与算法分析)