数据结构与算法笔记 lesson 21 线索二叉树

为什么使用线索二叉树


浪费了10*4个字节

使用中序遍历 H D I B E A F C G 可以利用“^”记录该结点的前去后继,节省指针浪费的空间。

如果是这种情况


需要将定义好的结构进行扩容

lchild , ltag , data, rtag, rchild

ltag为0 指向该结点的左孩子,为1时指向该结点的前驱

rtag为0 指向该结点的右孩子,为1时指向该结点的后继

   

线索二叉树的实现

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>

typedef char ElemType;

//线索存储标志位
//Link(0):表示指向左右孩子的指针
//Thread(1):表示指向前驱后继的线索
typedef enum {Link,Thread}PointerTag;

typedef struct BiThrNode
{
	char data;
	struct BiThrNode *lchild,*rchild;
	PointerTag ltag;
	PointerTag rtag;
}BiThrNode,*BiThrTree;

//全局变量,始终指向刚刚访问过的结点
BiThrTree pre;


//创建一棵二叉树,约定用户遵照前序遍历的方式输入数据
CreateBiThrTree(BiThrTree *T)
{
	char c;
	scanf("%c", &c);
	if (' ' == c)
	{
		*T = NULL;
	}
	else
	{
		*T = (BiThrNode*)malloc(sizeof(BiThrNode));
		(*T)->data = c;
		(*T)->ltag = Link;
		(*T)->rtag = Link;
		CreateBiThrTree(&(*T)->lchild);
		CreateBiThrTree(&(*T)->rchild);
	}
}

//中序遍历线索化
InThreading(BiThrTree T)
{
	if (T)
	{
		InThreading(T->lchild);//递归左孩子线索化
		//结点处理
		if (!T->lchild) //如果该结点没有左孩子,设置ltag为thread,并把lchild指向刚刚访问的结点
		{
			T->ltag = Thread;
			T->lchild = pre;
		}
		if (!pre->rchild)//如果上一个的右节点为空,没孩子
		{
			pre->rtag = Thread; //设置上一个节点rtag为线索
			pre->rchild = T;  
		}
		pre = T;
		InThreading(T->rchild);//递归右孩子线索化
	}
}

//
void InOrderThreading(BiThrTree *p,BiThrTree T)
{
	*p = malloc(sizeof(BiThrNode));//头指针
	(*p)->ltag = Link;
	(*p)->rtag = Thread;
	(*p)->rchild = *p;
	if (!T)
	{
		(*p)->lchild = *p;
	}
	else
	{
		(*p)->lchild = T;
		pre = *p;
		InThreading(T);
		pre->rchild = *p;
		pre->rtag = Thread;
		(*p)->rchild = pre;
	}
}

void visit(char c)
{
	printf("%c", c);
}
//中序遍历二叉树,非递归
void InOrderTraverse(BiThrTree T)
{
	BiThrTree p;
	p = T->lchild;
	while (p!=T)//p=T,头指针等于根节点 空树或者遍历到结束
	{
		while (p->ltag == Link)//有左子树
		{
			p = p->lchild;//找到最左节点
		}
		visit(p->data);
		while (p->rtag == Thread &&p->rchild != T)//有右子树,并且右节点不指向头
		{ 
			p = p->rchild;//说明有后继
			visit(p->data);
		}
		p = p->rchild;
	}
}


int main()
{
	BiThrTree P, T=NULL;
	CreateBiThrTree(&T);
	InOrderThreading(&P,T);
	printf("中序遍历输出结果为:");
	printf("\n");
	InOrderTraverse(P);
	printf("\n");
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值