线索二叉树

//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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值