6.3线索二叉树(二叉树的线索化)

6.3线索二叉树(二叉树的线索化)

问题引入:以二叉链表作为存储结构时。仅仅能得到结点的左、右孩子的信息。不能得到直接前驱、后继的信息。

问题解决:将二叉树线索化。

实现原理:n个结点的二叉树具有n+1个空指针域。利用这些空指针域存储结点的前驱、后继信息。

实质:线索化的实质是将二叉链表中的空指针改为指向前驱、后继的线索。


(1)二叉树的存储表示

enum {link,thread};//link=0; thread=1;
typedef struct bintree
{
	char data;
	struct bintree *lchild, *rchild;
	int ltag,rtag;//标志域。

指示 指针或线索 }BiNode, *BiTree;


(2)二叉树的创建

6.1二叉树的创建章节。


(3)中序线索化 及 遍历(注意凝视内容)

BiTree inorder_threading(BiTree thrt,BiTree t)
{
	thrt = (BiTree )malloc(len);//建立头指针
	if(!thrt)
		exit(0);
	thrt->rtag = thread;//右指针回指
	thrt->rchild = thrt;
	thrt->ltag = link;
	if(!t)//若二叉树空。左指针回指
		thrt->lchild = thrt;
	else
	{
		thrt->lchild = t;
		pre = thrt;

		in_threading(t);//中序遍历进行中序线索化
		
		pre->rtag = thread;//最后一个节点线索化
		pre->rchild = thrt;
		thrt->rchild = pre;
	}
	return thrt;
}
void in_threading(BiTree p)
{
	if(p)
	{
		in_threading(p -> lchild);//左子树线索化
		if(! p->lchild)//前驱线索
		{
			p->ltag = thread;
			p->lchild = pre;
		}
		if(! pre->rchild)//后继线索
		{
			pre->rtag = thread;
			pre->rchild = p;
		}
		pre = p;//保持pre指向 p 的前驱
		in_threading(p->rchild);//右子树线索化
	}
}
void inorder_traverse(BiTree thrt)
{
	BiTree p = thrt->lchild;
	while(p != thrt)//空树或遍历结束时,p==thrt
	{
		while(p->ltag == link)
		{
			p = p->lchild;
		}
		printf("%c ",p->data);
		if(p->rtag == thread && p->rchild != thrt)
		{
			p = p->rchild;
			printf("%c ",p->data);
		}
		p = p->rchild;
	}
}


(4)先序线索化 及 遍历

BiTree preorder_threading(BiTree thrt,BiTree t)
{
	thrt = (BiTree )malloc(len);
	if(! thrt)
		exit(0);
	thrt -> rtag = thread;
	thrt -> rchild = thrt;
	thrt -> ltag = link;

	if(!t)
		thrt -> lchild = thrt;
	else
	{
		thrt -> lchild = t;
		pre = thrt;

		pre_threading(t);
	
		pre -> rtag = thread;
		pre -> rchild = thrt;
		thrt -> rchild = pre;
	}
	return thrt;
}
void pre_threading(BiTree p)
{
	if(p)
	{
		if(! p->lchild)
		{
			p -> ltag = thread;
			p -> lchild = pre;
		}
		if(!p -> rchild)
			p -> rtag = thread;
		if(pre && pre->rtag == thread)
			pre -> rchild = p;
		pre = p;
		if(p->ltag == link)
			pre_threading(p -> lchild);
		if(p->rtag == link)
			pre_threading(p -> rchild);
	}
}
void preorder_traverse(BiTree thrt)
{
	BiTree p = thrt -> lchild;

	printf("%c ",p->data);
	while(p->rchild != thrt)
	{
		if(p->ltag == link)
			p = p->lchild;
		else
			p = p->rchild;

		printf("%c ",p->data);
	}
}


(5)后序线索化 及 遍历
BiTree postorder_threading(BiTree thrt,BiTree t)
{
	thrt = (BiTree )malloc(len);
	if(! thrt)
		exit(0);
	thrt -> rtag = thread;
	thrt -> rchild = thrt;
	thrt -> ltag = link;

	if(!t)
		thrt -> lchild = thrt;
	else
	{
		thrt -> lchild = t;
		pre = thrt;

		post_threading(t);
	
		pre -> rtag = thread;
		pre -> rchild = thrt;
		thrt -> rchild = pre;
	}
	return thrt;
}
void post_threading(BiTree p)
{
	if(p)
	{
		post_threading(p->lchild);   //左子树线索化
        post_threading(p->rchild);   //右子树线索化
		if(!p->lchild)
		{
			p->ltag=thread;
			p->lchild=pre;
		}
		if(!pre->rchild)
		{
			pre->rtag=thread;
			pre->rchild=p;
		}
		pre=p;
	}
}
void postorder_traverse(BiTree thrt)
{
	BiTree p = thrt;
	
	while(p->ltag==link||p->rtag==link)   //有左孩子先訪问左孩子,没有左孩子先訪问右孩子
	{
		while(p->ltag==link)    
			p=p->lchild;
		if(p->rtag==link)                //訪问左孩子为空的结点的右孩子
			p=p->rchild;
	}
	printf("%c ",p->data);
	while(p!=T)                        //p不为根结点
	{ 
		if(p->rtag==link)              //若p是有兄弟的左孩子
		{ 
			if(pre->rtag==thread||p==pre->rchild) //若p是双亲的右孩子或是独生左孩子,则后继为双亲
				p=pre;
			else 
			{ 
				p=pre->rchild;              //后继为双亲的右子树上依照后序遍历訪问的第一个结点。
				while(p->ltag==link||p->rtag==link)
				{ 
					while(p->ltag==link) 
						p=p->lchild;
					if(p->rtag==link)
						p=p->rchild;
			    }
			}
		}
		else 
			p=p->rchild;             //p指向后继
	
		printf("%c ",p->data);
	}
} 


(6)总程序源码(.c)

					/*  例子输入: abc##de#g##f###  */
# include <stdio.h>
# include <stdlib.h>
# define len (sizeof(BiNode))
# define OK 1

enum {link,thread};
typedef struct bintree
{
	char data;
	struct bintree *lchild, *rchild;
	int ltag,rtag;
}BiNode, *BiTree;

BiTree T, thrt, pre;

int bintree_creat(BiTree *q);
void welcome(BiTree t);

BiTree preorder_threading(BiTree thrt,BiTree t);//先序
void pre_threading(BiTree p);
void preorder_traverse(BiTree thrt);

BiTree inorder_threading(BiTree thrt,BiTree t);//中序 
void in_threading(BiTree p);
void inorder_traverse(BiTree thrt);

BiTree postorder_threading(BiTree thrt,BiTree t);//后序
void post_threading(BiTree p);
void postorder_traverse(BiTree thrt);

int main()
{
	printf("now create the bintree first,please input :
");
	bintree_creat(&T);

	welcome(T);

	return 0;
}

int bintree_creat(BiTree *q)
{
	char ch;
	ch=getchar();

	if(ch=='#')
		(*q)=NULL;
	else
	{
		(*q) = (BiTree )malloc(len);
		if((*q))
		{
			(*q)->data = ch;
			(*q)->ltag = link;
			(*q)->rtag = link;
			bintree_creat(&(*q) -> lchild);
			bintree_creat(&(*q) -> rchild);
		}
	}

	return OK;
}

void welcome(BiTree t)
{
	int i;
	printf("input 1 :preorder_threading the bintree .
");
	printf("input 2 :inorder_threading the bintree .
");
	printf("input 3 :postorder_threading the bintree .

");
	scanf("%d",&i);

	switch (i)
	{
		case 1 :thrt = preorder_threading(thrt,t);
				preorder_traverse(thrt);
				printf("

"); break;
				
		case 2 :thrt = inorder_threading(thrt,t);
				inorder_traverse(thrt);
				printf("

"); break;

		case 3 :thrt = postorder_threading(thrt,t);
				postorder_traverse(thrt);
				printf("

"); break;

		default :printf("input error !");
				 exit(1);
	}
}

BiTree preorder_threading(BiTree thrt,BiTree t)
{
	thrt = (BiTree )malloc(len);
	if(! thrt)
		exit(0);
	thrt -> rtag = thread;
	thrt -> rchild = thrt;
	thrt -> ltag = link;

	if(!t)
		thrt -> lchild = thrt;
	else
	{
		thrt -> lchild = t;
		pre = thrt;

		pre_threading(t);
	
		pre -> rtag = thread;
		pre -> rchild = thrt;
		thrt -> rchild = pre;
	}
	return thrt;
}
void pre_threading(BiTree p)
{
	if(p)
	{
		if(! p->lchild)
		{
			p -> ltag = thread;
			p -> lchild = pre;
		}
		if(!p -> rchild)
			p -> rtag = thread;
		if(pre && pre->rtag == thread)
			pre -> rchild = p;
		pre = p;
		if(p->ltag == link)
			pre_threading(p -> lchild);
		if(p->rtag == link)
			pre_threading(p -> rchild);
	}
}
void preorder_traverse(BiTree thrt)
{
	BiTree p = thrt -> lchild;

	printf("%c ",p->data);
	while(p->rchild != thrt)
	{
		if(p->ltag == link)
			p = p->lchild;
		else
			p = p->rchild;

		printf("%c ",p->data);
	}
}

BiTree inorder_threading(BiTree thrt,BiTree t)
{
	thrt = (BiTree )malloc(len);//建立头指针
	if(!thrt)
		exit(0);
	thrt->rtag = thread;//右指针回指
	thrt->rchild = thrt;
	thrt->ltag = link;
	if(!t)//若二叉树空,左指针回指
		thrt->lchild = thrt;
	else
	{
		thrt->lchild = t;
		pre = thrt;

		in_threading(t);//中序遍历进行中序线索化
		
		pre->rtag = thread;//最后一个节点线索化
		pre->rchild = thrt;
		thrt->rchild = pre;
	}
	return thrt;
}
void in_threading(BiTree p)
{
	if(p)
	{
		in_threading(p -> lchild);//左子树线索化
		if(! p->lchild)//前驱线索
		{
			p->ltag = thread;
			p->lchild = pre;
		}
		if(! pre->rchild)//后继线索
		{
			pre->rtag = thread;
			pre->rchild = p;
		}
		pre = p;//保持pre指向 p 的前驱
		in_threading(p->rchild);//右子树线索化
	}
}
void inorder_traverse(BiTree thrt)
{
	BiTree p = thrt->lchild;
	while(p != thrt)//空树或遍历结束时,p==thrt
	{
		while(p->ltag == link)
		{
			p = p->lchild;
		}
		printf("%c ",p->data);
		if(p->rtag == thread && p->rchild != thrt)
		{
			p = p->rchild;
			printf("%c ",p->data);
		}
		p = p->rchild;
	}
}

BiTree postorder_threading(BiTree thrt,BiTree t)
{
	thrt = (BiTree )malloc(len);
	if(! thrt)
		exit(0);
	thrt -> rtag = thread;
	thrt -> rchild = thrt;
	thrt -> ltag = link;

	if(!t)
		thrt -> lchild = thrt;
	else
	{
		thrt -> lchild = t;
		pre = thrt;

		post_threading(t);
	
		pre -> rtag = thread;
		pre -> rchild = thrt;
		thrt -> rchild = pre;
	}
	return thrt;
}
void post_threading(BiTree p)
{
	if(p)
	{
		post_threading(p->lchild);   //左子树线索化
        post_threading(p->rchild);   //右子树线索化
		if(!p->lchild)
		{
			p->ltag=thread;
			p->lchild=pre;
		}
		if(!pre->rchild)
		{
			pre->rtag=thread;
			pre->rchild=p;
		}
		pre=p;
	}
}
void postorder_traverse(BiTree thrt)
{
	BiTree p = thrt;
	
	while(p->ltag==link||p->rtag==link)   //有左孩子先訪问左孩子,没有左孩子先訪问右孩子
	{
		while(p->ltag==link)    
			p=p->lchild;
		if(p->rtag==link)                //訪问左孩子为空的结点的右孩子
			p=p->rchild;
	}
	printf("%c ",p->data);
	while(p!=T)                        //p不为根结点
	{ 
		if(p->rtag==link)              //若p是有兄弟的左孩子
		{ 
			if(pre->rtag==thread||p==pre->rchild) //若p是双亲的右孩子或是独生左孩子,则后继为双亲
				p=pre;
			else 
			{ 
				p=pre->rchild;              //后继为双亲的右子树上依照后序遍历訪问的第一个结点。
				while(p->ltag==link||p->rtag==link)
				{ 
					while(p->ltag==link) 
						p=p->lchild;
					if(p->rtag==link)
						p=p->rchild;
			    }
			}
		}
		else 
			p=p->rchild;             //p指向后继
	
		printf("%c ",p->data);
	}
} 

(7)撰写匆忙,表述简陋。必有疏漏。欢迎朋友们批评指正。

2014/10/21




原文地址:https://www.cnblogs.com/yxysuanfa/p/6962449.html