线索二叉树,中序遍历线索二叉树

//二叉树中序线索化,中序遍历线索化二叉树
//线索化意为填充结点中的空指针,若原为左子树则放入前驱结点,右子树则放入后继结点
//相比二叉链表表示法,增加左右标签,1为线索(实际访问),0为子树(图上看到的)
#include<stdio.h>
#include<stdlib.h>
typedef struct BinaryTree
{
	int data;
	struct BinaryTree* lchild;
	struct BinaryTree* rchild;
	int LTag;//左线索
	int RTag;//右线索
}Tree;
void CreateTree(Tree** t)
{
	int ch;
	printf("输入数字\n");
	scanf("%d", &ch);
	if (!ch)
		*t = NULL;
	else
	{
		*t = (Tree*)malloc(sizeof(Tree));
		(*t)->data = ch;
		(*t)->LTag = 0;
		(*t)->RTag = 0;
		CreateTree(&(*t)->lchild);
		CreateTree(&(*t)->rchild);
	}
}

//中序线索化
//主体思路:先创建一个头节点Thrt,左指针指向根节点,右侧存放最后一个遍历到的结点
//中序遍历到的首节点左指针与末节点右指针都指向Thrt,方便从末节点反向遍历
//线索化的过程中,用pre保存前驱结点,由于调用的函数要用到Thrt和pre,故设全局变量
//由于只有遍历时才能得到前驱结点,所以线索化时需要递归,故将线索化的准备工作(如
//创建头结点并对其赋值及完整最后一个遍历到的结点)与需递归的函数分开
//递归函数中,若有需要(原先为空指针,需赋线索)
//则在执行结点时对其前驱结点及其前驱结点的后驱(即当前结点)赋值
//为使赋值成功,此处函数调用中传参均为指向节点指针的地址(Tree**)
//故调用完递归函数后还要对最后一个结点的后继结点赋值
Tree* Thrt = NULL;
Tree* pre = NULL;
void InThreading(Tree** p);
void InorderThreading(Tree** t)
{
	
	Thrt = (Tree*)malloc(sizeof(Tree));
	if (!Thrt)
	{
		printf("建立头结点失败\n");
		return;
	}
	Thrt->data = 0;
	Thrt->LTag = 0;
	Thrt->RTag = 1;
	Thrt->lchild = Thrt;
	if (!*t)
		Thrt->rchild = Thrt;
	else
	{
		Thrt->lchild = *t;
		pre = Thrt;
		InThreading(t);
		pre->RTag = 1;
		pre->rchild = Thrt;
		Thrt->rchild = pre;
	}
}
//调用的递归函数
void InThreading(Tree** p)
{
	if (*p)
	{
		InThreading(&(*p)->lchild);
		if (!(*p)->lchild)
		{
			(*p)->LTag = 1;
			(*p)->lchild = pre;
		}
		if(!pre->rchild)
		{
			pre->RTag = 1;
			pre->rchild = *p;
		}
		pre = *p;
		InThreading(&(*p)->rchild);
	}
}

//中序遍历线索二叉树
//先向左遍历,直到左标签为1(为1即原本此处指针为空,无子树)
//执行该节点,若右侧是后继结点且非头结点,则直接遍历右侧直到其右侧不是后继结点
//若是普通的子树,则回到第一步,对该右侧结点向左遍历
void Print(Tree* p)
{
	printf("%d ", p->data);
}
void InorderThreadingTraverse(Tree* p)
{
	while (p != Thrt)
	{
		while (!p->LTag)
			p = p->lchild;
		Print(p);
		while (p->RTag && p->rchild != Thrt)
		{
			p = p->rchild;
			Print(p);
		}
		p = p->rchild;
	}
}

int main()
{
	Tree* t = NULL;
	CreateTree(&t);
	InorderThreading(&t);
	InorderThreadingTraverse(t);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值