小蚂蚁学习数据结构(21)——线索二叉树的建立遍历代码实现

    今天写了一下线索二叉树的创建和遍历,感觉还可以,不算很难,把思路理清楚之后,就好下手了。

    记得刚开始看数据结构的时候,感觉非常头疼,现在越来越感觉有意思了,当然,主要是在解决了一个问题之后的成就感让人很满足。

/*
	线索二叉树的建立,遍历代码实现
*/
# include <stdio.h>
# include <stdlib.h>
# include <malloc.h>

//这里失误了,刚开始都加了";"号,导致报错missing ')' before ';'
# define LINK 	0
# define THREAD 1
# define OK 	1
# define ERROR	0

typedef char TElemType;
typedef int	Status;	

/*
	线索树节点
*/
typedef struct BiThrNode
{
	TElemType data;
	struct BiThrNode * lchild, * rchild;	//左右孩子的指针
	Status LTag, RTag;
}BITHRTREE, * PBITHRTREE;

//定义一个全局变量pre,用于指定一个前驱元素
PBITHRTREE pre = NULL;

/*
	创建一颗二叉树
	第一次定义这个函数的时候是这样写的
	Status CreateTree( PBITHRTREE );
	报错:error C2668: 'CreateTree' : ambiguous call to overloaded function
	原因是使用了引用,而在函数前置中没有体现出来,需要改为:
	Status CreateTree( PBITHRTREE &  );
*/
Status CreateTree( PBITHRTREE &  );

/* 使用递归的方法,中序遍历二叉树 */
Status InOrderTraveler( PBITHRTREE & );

/* 为二叉树添加线索 */
Status InOrderTreading( PBITHRTREE &, PBITHRTREE );

/* 中序遍历的方式添加线索 */
Status InThreading( PBITHRTREE );

/* 按照线索遍历二叉树 */
Status InOrderTraveler_Thread( PBITHRTREE & );

/*
	创建一个二叉树,空格代表无子树。
	函数的形参,使用引用的方式,操作简便。
*/
Status CreateTree( PBITHRTREE &BaseTree )
{
	TElemType data;
	
	scanf( "%c", &data );
	
	if( ' ' == data )
	{
		BaseTree = NULL;
	}
	else
	{
		BaseTree = ( PBITHRTREE )malloc( sizeof( BITHRTREE ) );
		BaseTree -> data = data;
		CreateTree( BaseTree -> lchild );
		CreateTree( BaseTree -> rchild );
	}
	
	return OK;
}

/*
	使用递归的方法,中序遍历二叉树
	PS:其实写这个中序遍历的函数,主要是想看看方才的二叉树生成了没
	……囧……
*/
Status InOrderTraveler( PBITHRTREE &BaseTree )
{
	if( NULL != BaseTree )
	{
		InOrderTraveler( BaseTree -> lchild );
		printf( "%c", BaseTree -> data );
		InOrderTraveler( BaseTree -> rchild );
	}
	
	return OK;
}

/*
	为一个二叉树添加线索,以中序为例
	@param	PBITHRTREE	&ThreadTree 要生成的线索二叉树
	@param	PBITHRTREE	&BaseTree	已经生成基础二叉树
	return Status;
*/
Status InOrderTreading( PBITHRTREE &ThreadTree, PBITHRTREE BaseTree )
{
	//创建一个头结点
	ThreadTree = ( PBITHRTREE )malloc( sizeof( BITHRTREE ) );

	ThreadTree -> LTag = LINK;
	ThreadTree -> RTag = THREAD;
	ThreadTree -> rchild = ThreadTree;	//右指针回指
	
	if( NULL == BaseTree )
	{
		ThreadTree -> lchild = ThreadTree; //基础树为空,这左孩子回指
	}
	else
	{
		ThreadTree -> lchild = BaseTree;
		// 这里需要一个全局变量,来指示前驱元素
		pre = ThreadTree;
		
		InThreading( BaseTree );
		
		pre -> RTag = THREAD;
		pre -> rchild = ThreadTree;
		ThreadTree -> rchild = pre;
	}
	
	return OK;
}

/* 中序的方式设置线索 */
Status InThreading( PBITHRTREE Tree )
{
	if( NULL != Tree )
	{
		InThreading( Tree -> lchild );
		
		if( NULL == Tree -> lchild )
		{
			//如果右孩子是空,那么放入前驱元素
			Tree -> LTag = THREAD;
			Tree -> lchild = pre;
		}
		
		if( NULL == pre -> rchild )
		{
			/*  
				如果这个前驱元素的右孩子为空,就把当前节点的指针赋予它
				作为后继元素
			*/
			pre -> RTag = THREAD;
			pre -> rchild = Tree;
		}
		pre = Tree;
		
		InThreading( Tree -> rchild );
	}
	
	return OK;
}

/* 按照线索遍历二叉树 */
Status InOrderTraveler_Thread( PBITHRTREE & Tree )
{
	
	PBITHRTREE p = Tree -> lchild;
	
	while( p != Tree )
	{
		/*
			首先,一路查找每个元素的ltag是不是等于1
			如果等于1,说明这是第一个节点,将其值输出
			注意!!!
			怎么会这样呢?(其实我想说个我草),下行一开始写的
			while( p -> LTag != LINK )
			无法找到第一个节点,导致遍历出错,以后长点心吧
		*/
		while( p -> LTag != THREAD )
		{
			//printf( "遍历到了%c,他的LTag是%d\n", p -> data, p -> LTag );
			p = p -> lchild;
		}
		
		//循环退出,说明这是第一个节点,输出其值
		printf( "%c", p -> data );
		
		/*
			查看他的LTag,如果也是1,说明是线索,直接输出
			如果不是1,说明他有孩子,将指针下移一位,
			从第一个while那里按照这里的思路再循环一次
		*/
		while( p -> RTag == THREAD && p -> rchild != Tree )
		{
			p = p -> rchild;
			printf( "%c", p -> data );
		}
		
		p = p -> rchild;
	}
	
	return OK;
}

Status main( void )
{
	PBITHRTREE ThreadTree = NULL, BaseTree = NULL;
	//首先建造一颗不带线索的二叉树
	printf( "请输入一颗二叉树:\n" );
	CreateTree( BaseTree );
	
	printf( "中序递归遍历二叉树:\n" );
	InOrderTraveler( BaseTree );
	printf( "\n" );
	
	printf( "将刚才创造的二叉树线索化。……  Lording ……" );
	InOrderTreading( ThreadTree, BaseTree );
	
	printf( "\n" );
	
	printf( "按照线索遍历二叉树:\n" );
	InOrderTraveler_Thread( ThreadTree );
	printf( "\n" );
	
	return 0;
}
/*
	VC++6.0中输出的结果是
	=======================================
	请输入一颗二叉树:
	ABEQ  F   CD
	中序递归遍历二叉树:
	QEFBADC
	将刚才创造的二叉树线索化。……  Lording ……
	按照线索遍历二叉树:
	QEFBADC
	=======================================
	总结:
		需要总结的地方太多了,都是一些白痴性错误,逻辑上还是比较清晰的。
		比如说:
			预定义不用就加“;”
			修改函数类型的时候,记得把前置函数定义哪里也修改了
			还有就是需要在编写的时候,再 认真一些。

*/


     学PHP的小蚂蚁 博客 http://my.oschina.net/woshixiaomayi/blog



转载于:https://my.oschina.net/woshixiaomayi/blog/607605

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值