//ThreadBinTree.c
//创建线索二叉树
typedef enum
{
SubTree,
Thread
}NodeFlag; //枚举SubTree(子树)和Thread(线索)分别为0,1
typedef struct ThreadTree //定义线索二叉树结点类型
{
DATA data; //元素数据
NodeFlag lflag; //左标志
NodeFlag rflag; //右标志
struct ThreadTree *left; //左子树结点指针
struct ThreadTree *right; //右子树结点指针
}ThreadBinTree;
//对二叉树进行中序线索化
void BinTreeThreading_LDR(ThreadBinTree *bt) //二叉树按中序线索化
{
if(bt) //结点非空时,当前访问结点
{
BinTreeThreading_LDR(bt->left); //递归调用,将左子树线索化
bt->lflag=(bt->left)?SubTree:Thread; //设置左指针域的指针
bt->rflag=(bt->right)?SubTree:Thread; //设置右指针域的指针
if(Previous) //若当前结点的前驱Previous存在
{
if(Previous->rflag==Thread) //若当前结点的前驱右标志为线索
Previous->right=bt; //设Previous的右线索指向后继
if(bt->lflag==Thread) //若当前结点的左标志为线索
bt->left=Previous; //设当前结点的左线索指向中序前驱
}
Previous=bt; //让Previous保存刚访问的结点
BinTreeThreading_LDR(bt->right); //递归调用,将右子树线索化
}
}
//查找后继结点
//创建线索二叉树后,可以根据给定的某个结点求出其前驱或后继结点。
ThreadBinTree *BinTreeNext_LDR(ThreadBinTree *bt) //求指定结点的后继
{
ThreadBinTree *nextnode;
if(!bt)
return NULL; //若当前结点为空,则返回空
if(bt->rflag==Thread) //若当前结点的右子树为空
return bt->right; //返回右线索所指的中序后继
else
{
nextnode=bt->right; //从当前结点的右子树开始查找
while(nextnode->lflag==SubTree) //循环处理所有左子树不为空的结点
nextnode=nextnode->left;
return nextnode; //返回左下方的结点
}
}
//查找前驱结点
/*在中序线索二叉树中,查找指定结点的前驱和查找后继的方法类似,具体来说分为如下
两种情况:
如果结点m的左子树为空,则m->left为左线索,直接指向m的中序前驱结点。
如果结点m的左子树非空,则从m的左子树出发,沿着该子树的右指针链往下查
找,一直找到一个没有右子树的结点为止,则该结点久是结点m的中序前驱结点。*/
ThreadBinTree *ThreadTreePrevious_LDR(ThreadBinTree *bt) //求指定结点的前驱
{
ThreadBinTree *prenode; //若当前结点为空,则返回空
if(!bt)
return NULL; //若当前结点为空,则返回空
if(bt->lflag==Thread) //若当前结点的左子树为空
return bt->left; //返回左线索所指的中序后继
else
{
nextnode=bt->left; //从当前结点的左子树开始查找
while(nextnode->rflag==SubTree) //循环处理所有左子树不为空的结点
nextnode=nextnode->left;
return nextnode; //返回左下方的结点
}
}
//遍历线索二叉树
//在遍历线索二叉树时,无须使用递归调用,只根据后继指针即可完成遍历。
void ThreadBinTree_LDR(ThreadBinTree *bt,void (*oper) (ThreadBinTree *p))//遍历中序线索二叉树
{
if(bt) //二叉树不为空
{
while(bt->lflag==SubTree) //有左子树
bt=bt->left; //从根往下找最左下结点,即中序序列的开始查找
do{
oper(bt);//处理结点
bt=BinTreeNext_LDR(bt); //找中序后继结点
}while(bt);
}
}
#include<stdio.h>
#include "ThreadBinTree.c"
void oper(ThreadBinTree *p) //操作二叉树结点数据
{
printf("%c ",p->data);//输出数据
return ;
}
ThreadBinTree *InitRoot() //初始化二叉树的根
{
ThreadBinTree *node;
if(node=(ThreadBinTree *)malloc(sizeof(ThreadBinTree))) //分配内存
{
printf("\n输入根结点数据:");
scanf("%s",&node->data);
node->left=NULL;
node->right=NULL;
return BinTreeInit(node);
}
return NULL;
}
//编写AddNode(),用于向二叉树指定的结点添加子结点
void AddNode(ThreadBinTree *bt)
{
ThreadBinTree *node,*parent;
DATA data;
char select;
if(node=(ThreadBinTree *)malloc(sizeof(ThreadBinTree))) //分配内存
{
printf("\n输入二叉树结点数据:");
fflush(stdin); //清空输入缓冲区
scanf("%s",&node->data);
node->left=NULL;
node->right=NULL;
printf("输入父结点数据:");
fflush(stdin); //清空输入缓冲区
scanf("%s",&data);
parent=BinTreeFind(bt,data); //查找指定数据的结点
if(!parent)
{
printf("未找到父结点!\n");
free(node); //释放创建的结点内存
return ;
}
printf("1.添加到左子树\n2.添加到右子树\n");
do{
select=getchar();
select-='0';
if(select==1||select==2)
BinTreeAddNode(parent,node,select);
}while(select!=1&&select!=2);
return ;
}
}
int main()
{
ThreadBinTree *root=NULL; //root为指向二叉树根结点的指针
char select;
void (*oper1) (); //指向函数的指针
oper1=oper; //指向具体操作的函数
do{
printf("\n1.设置二叉树根元素 2.添加二叉树根结点\n");
printf("3.生成中序线索二叉树 3.遍历线索二叉树\n");
printf("0.退出\n");
select=getchar();
switch(select){
case '1': //设置根元素
root=InitRoot();
break;
case '2':
AddNode(root);
break;
case '3': //生成中序线索二叉树
ThreadBinTreading_LDR(root);
printf("\n生成中序线索二叉树完毕!\n");
break;
case '4':
printf("\n中序线索二叉树遍历的结果: ");
ThreadBinTree_LDR(root,oper1);
printf("\n");
break;
case '0':
break;
}
}while(select!='0');
BinTreeClear(root); //清空二叉树
getchar();
return 0;
}