今天写了一下线索二叉树的创建和遍历,感觉还可以,不算很难,把思路理清楚之后,就好下手了。
记得刚开始看数据结构的时候,感觉非常头疼,现在越来越感觉有意思了,当然,主要是在解决了一个问题之后的成就感让人很满足。
/*
线索二叉树的建立,遍历代码实现
*/
# 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