数据结构 树(线索二叉树)

/*
二叉树的链式存储中不能够得到一个结点的前驱和后继的信息
这些信息只有在遍历的动态过程中才能得到。
为了保存这种在遍历中也可得到的信息
最简单的方法就是为每一个结点增加两个指针域;fwd和bkwd


注:此处的前驱和后继为:遍历过程中的前驱和后继(误解:该结点的父节点和子节点)




另外在n个结点中,必存在n+1个空链域(因为满二叉树总结点树2n+1,个人理解的)
由此设想能否利用这些空链域来存放结点的前驱和后继的信息:
   试做一下规定:
   如果有左孩子:lchild就存左孩子,否则lchild存前驱
   如果有右孩子:rchild就存右孩子,否则rchild存后继

   增加两个标志域;
   lchild  LTag   date  RTag rchild

   LTag=0  lchild 存左孩子
       =1  lchild 存前驱
   RTag=0  rchild 存右孩子
       =1  rchild 存后继

这样的存储结构:叫做线索链表
  直线前驱和后继的指针,叫做线索
      加上线索的二叉树叫做;线索二叉树


*/

//二叉树的二叉先说存储表示
#include "stdio.h"
#include "stdlib.h"
#include "malloc.h"

typedef enum PointerTag{Link,Thread};//Link==0 指针, Thread ==1 线索
typedef char TElemType;
typedef struct BiThrNode
{
	char data;
	struct BiThrNode *lchild,*rchild;
	PointerTag LTag,RTag;
}BiThrNode,*BiThrTree;


void CreateBiTree(BiThrTree *T)//按先序遍历创建二叉树   T为bt的地址  *T为bt
{
	TElemType ch;
	scanf("%c",&ch);
	//ch = getchar();
	if(ch=='#'){
		*T = NULL;
	}else
	{
		*T= (BiThrTree)malloc(sizeof(BiThrNode));
		if((*T)==NULL)//和(!(*T))一样都是T为空时 表达式true,执行
		{
			exit(1);
		}
		else
		{
			(*T)->data = ch;
			CreateBiTree(&((*T)->lchild)); //bt->lchild是一个指针,参数要为指针的地址,故取地址
			if((*T)->lchild)
			{
				(*T)->LTag=Link;
			}
			CreateBiTree(&((*T)->rchild));
			if((*T)->rchild)
			{
				(*T)->RTag=Link;
			}
		}
	}
}


/*
中序遍历线索化的递归函数代码
*/
BiThrTree pre ;


void InThreading(BiThrTree T)
{
	
	if(T)
	{
		InThreading(T->lchild);//递归左子树线索化
		/
		if(!T->lchild)//如果没有左孩子
		{
			T->LTag=Thread;//前驱线索
			T->lchild = pre;

		}
		if(!pre->rchild)//如果没有右孩子 (此处判断的当前结点的左孩子和,上面判断的没有右孩子为同一结点,因为当当前结点没有左孩子时:该结点被改变所以用pre保存当前结点)
		{
			pre->RTag = Thread;//后继线索
			pre->rchild = T;//前驱右孩子指针指向后继(当前结点T)
		}
		pre = T;  //保存pre指向T的前驱
		/
		InThreading(T->rchild);//递归右子树线索化

	}
}

void InOrderThreading(BiThrTree *Thrt,BiThrTree T)
{

	(*Thrt)=(BiThrTree)malloc(sizeof(BiThrNode));
	if((*Thrt)==NULL)
	{
		return ;
	}
	/*if(!((*Thrt)=(BiThrTree)malloc(sizeof(BiThrNode))))
		exit(1);
		*/
	(*Thrt)->LTag = Link;  //建立结点
	(*Thrt)->RTag = Thread;
	(*Thrt)->rchild = (*Thrt);//右指针回指
	if(T==NULL)
	{
		(*Thrt)->lchild = (*Thrt);//为空,左指针回指
	}
	else
	{
		(*Thrt)->lchild =T;
		pre = (*Thrt);
		InThreading(T);  //中序遍进行中序线索化
		//最后一个节点线索化
		pre->rchild = (*Thrt); 
		pre->RTag = Thread;
		(*Thrt)->rchild = pre;

	}
}
//遍历二叉树
void InOrderTraverse_Thr(BiThrTree T)
{
	//T指向头节点,头节点的左链lchild指向根节点
	//中序遍历二叉树T的非递归算法
	BiThrTree p;
	p = T->lchild;
	while(p!=T)
	{
		while(p->LTag==Link)//LTag==0时循环到中序序列第一个结点
		p=p->lchild;
		printf("%c",p->data);
		while(p->RTag==Thread&&p->rchild!=T)
		{
			p=p->rchild;
			printf("%c",p->data);
		}
		p=p->rchild;
	}
	return ;
	
}


void main()
{
	BiThrTree T,H;	/*ABDH#K###E##CFI###G#J##*/
	//创建二叉树
	CreateBiTree(&T);
	
	InOrderThreading(&H,T);
	printf("中序遍历(输出)线索二叉树:\n");
	InOrderTraverse_Thr(H);//注此处参数为 H非T
	printf("\n");

   

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值