#define MAXSIZE 100
#include <stdlib.h>
#include <stdio.h>
typedef char DATA;
typedef enum
{
SubTree,
Thread
}NodeFlag;
typedef struct ThreadTree
{
DATA data;
NodeFlag lflag;
NodeFlag rflag;
struct ThreadTree *left;
struct ThreadTree *right;
}ThreadBinTree;
ThreadBinTree * Previous = NULL;
/************************************************************************
函数名称:BinTreeThreading_LDR
函数功能:对二叉树进行中序线索化
函数参数:bt为结点指针
函数返回:无
************************************************************************/
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)//若当前结点的前驱存在
{
if (Previous->rflag == Thread)//当前结点的前驱的右标识为线索,则前驱的右指针该指向当前结点
Previous->right = bt;
if (bt->lflag == Thread)
bt->left = Previous;
}
Previous = bt;
BinTreeThreading_LDR(bt->right);
}
}
/*************************************************************************************
查找后继结点:
在中序线索二叉树中,查找结点p的中序后继结点分两种情况:
1:若结点p的右子树为空(即p->rflag == Thread),则p->right为右线索,直接指向p的中序后继。
2:若结点p的右子树不为空(即p->rflag == SubTree),则p的中序后继必是其右子树中第一个中序
遍历到的结点。
**************************************************************************************/
/************************************************************************
函数名称:BinTreeNext_LDR
函数功能:对二叉树进行中序线索化之后查找后继结点
函数参数:bt为结点指针
函数返回:bt的后继结点的指针
************************************************************************/
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;
}
return NULL;
}
/*************************************************************************************
查找前驱结点:
在中序线索二叉树中,查找结点p的中序前驱结点分两种情况:
1:若结点p的左子树为空(即p->lflag == Thread),则p->left为左线索,直接指向p的中序前驱。
2:若结点p的左子树不为空(即p->lflag == SubTree),则从p的左子树出发,沿该子树的右指针链
往下查找,直到找到一个没有右子树的结点为止。
**************************************************************************************/
/************************************************************************
函数名称:BinTreePrevious_LDR
函数功能:对二叉树进行中序线索化之后查找前驱结点
函数参数:bt为结点指针
函数返回:bt的前驱结点的指针
************************************************************************/
ThreadBinTree *BinTreePrevious_LDR(ThreadBinTree *bt)
{
ThreadBinTree * prenode;
if (!bt) return NULL;
if (bt->lflag == Thread)
return bt->left;
else
{
prenode = bt->left;
while (prenode->lflag == SubTree)
prenode = prenode->right;
return prenode;
}
}
/************************************************************************
函数名称:oper
函数功能:输出该结点的数据
函数参数:p为结点指针
函数返回:无
************************************************************************/
void oper(ThreadBinTree *p)
{
printf("%c ", p->data);
return;
}
/************************************************************************
函数名称:ThreadBinTree_LDR
函数功能:对二叉树进行中序遍历
函数参数:bt为结点指针
函数返回:无
************************************************************************/
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);
}
}
/************************************************************************
函数名称:ThreadBinTree_LDR
函数功能:对二叉树进行中序遍历
函数参数:bt为结点指针
函数返回:无
************************************************************************/
ThreadBinTree * InitRoot()
{
ThreadBinTree *node;
if (node = (ThreadBinTree *)malloc(sizeof(ThreadBinTree)))
{
printf("\n输入根结点数据:");
//scanf("%s", &node->data);
node->data = getchar();
node->left = NULL;
node->right = NULL;
return node;
}
}
/************************************************************************
函数名称:BinTreeAddNode
函数功能:添加结点到二叉树
函数参数:bt为父结点,node为子结点,n=1表示添加左子树,n=2表示添加右子树
函数返回:成功返回1,失败返回0
************************************************************************/
int BinTreeAddNode(ThreadBinTree *bt, ThreadBinTree *node, int n)
{
if (bt == NULL)
{
printf("父结点不存在,请先设置父结点!\n");
return 0;
}
switch(n)
{
case 1: //添加到左结点
if (bt->left)
{
printf("左子树不为空!\n");
return 0;
}
else
bt->left = node;
break;
case 2://添加到右结点
if (bt->right)
{
printf("右子树不为空!\n");
return 0;
}
else
bt->right = node;
break;
default:
printf("输入错误!\n");
return 0;
}
return 1;
}
/************************************************************************
函数名称:BinTreeFind
函数功能:在树中查找某个数值等于data的结点
函数参数:bt为父结点, 数值为data
函数返回:若没有找到返回NULL,若找到返回该结点的指针
************************************************************************/
ThreadBinTree *BinTreeFind(ThreadBinTree *bt, DATA data)
{
ThreadBinTree *p;
if (bt == NULL)
return NULL;
else
{
if (bt->data == data)
return bt;
else
{
if (p = BinTreeFind(bt->left, data))
return p;
else if (p = BinTreeFind(bt->right, data))
return p;
else
return NULL;
}
}
}
/************************************************************************
函数名称:AddNode
函数功能:添加结点到二叉树
函数参数:bt为父结点
函数返回:成功返回1,失败返回0
************************************************************************/
void AddNode(ThreadBinTree *bt)
{
ThreadBinTree * node, *parent;
DATA data;
char select;
if (node = (ThreadBinTree *)malloc(sizeof(ThreadBinTree)))
{
printf("\n输入二叉树结点数据:");
fflush(stdin);//清空输入缓冲区
// scanf("%c", &node->data);
node->data = getchar();
node->left = NULL;
node->right = NULL;
printf("输入父结点数据:");
fflush(stdin);
// scanf("%c", &data);
data = getchar();
parent = BinTreeFind(bt, data);
if (!parent)
{
printf("未找到父结点!\n");
free(node);
return;
}
printf("1.添加到左子树\n2.添加到右子树\n");
do
{
select = getchar();
select = select - '0';
if (select == 1 || select == 2)
BinTreeAddNode(parent, node, select);
}while(select != 1 && select != 2);
}
return;
}
/************************************************************************
函数名称:BinTreeClear
函数功能:清空二叉树,释放每个结点的内存,使树变为空树
函数参数:bt为父结点
函数返回:没有返回值
************************************************************************/
void BinTreeClear(ThreadBinTree *bt)
{
if (bt)
{
BinTreeClear(bt->left);
BinTreeClear(bt->right);
free(bt);
bt = NULL;
}
return;
}
/************************************************************************
函数名称:main
函数功能:主函数
函数参数:无
函数返回:成功返回0
************************************************************************/
int main()
{
ThreadBinTree *root = NULL;
char select;
do
{
system("cls");
printf("1.设置二叉树根元素 2.添加二叉树结点\n");
printf("3.生成中序线索二叉树 4.遍历线索二叉树\n");
printf("0.退出\n");
select = getchar();
getchar();
switch(select)
{
case '1':
root = InitRoot();
getchar();
getchar();
break;
case '2':
AddNode(root);
getchar();
break;
case '3':
BinTreeThreading_LDR(root);
printf("\n生成中序线索二叉树完毕!\n");
getchar();
break;
case '4':
printf("\n中序线索二叉树遍历的结果:");
ThreadBinTree_LDR(root, oper);
printf("\n");
getchar();
break;
case '0':
break;
default:
break;
}
}while(select != '0');
BinTreeClear(root);
root = NULL;
getchar();
getchar();
return 0;
}