线索二叉树(中序索引)

本文介绍了一种实现二叉树中序线索化的方法,并提供了详细的C语言代码实现。通过对二叉树进行中序线索化,可以有效地提高中序遍历的效率,避免递归调用带来的开销。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<stdio.h>
#include<stdlib.h>
#include<malloc.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;

//创建一棵二叉树,约定用户遵守前序遍历的方式输入数据
void 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);
	}
}
//中序遍历线索化
void InThreading(BiThrTree T)
{
	if(T)
	{
		InThreading(T->lchild);
		
		if(!T->lchild)
		{
			T->ltag = Thread;
			T->lchild = pre;
		}
		if(!pre->rchild)
		{
			pre->rtag = Thread;
			pre->rchild = T;
		}
		pre = T;
		InThreading(T->rchild);
	}
}
void InOrderThreading(BiThrTree *p,BiThrTree T)
{
	*p = (BiThrTree)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)
	{
		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("output:\n");
	InOrderTraverse(P);
	printf("\n");
	return 0;
}

### 后遍历二叉树进行中线索化 对于后遍历的二叉树,在对其进行中线索化的过程中,主要目标是在不改变原有结构的前提下,通过修改空指针指向来加速特定类型的遍历操作。具体来说: #### 中线索化的定义与目的 中线索化是指对一棵二叉树中的所有节点的空指针域按照中遍历的方式添加线索的过程[^2]。这种处理使得可以在不需要额外栈空间的情况下完成中遍历。 #### 实现细节 为了实现这一功能,通常会引入两个标志位`ltag`和`rtag`分别表示左孩子或右孩子的链接类型(真实的孩子还是前驱/后继)。当`ltag=0`时意味着该位置存储的是实际的儿子;而如果设置为1,则说明这是一个线索,即它应该指向某个祖先或者子孙作为逻辑上的前驱者或者是继承者。同理适用于右边的情况。 针对后构建好的二叉链表做中线索单元测试可以遵循以下模式: - 初始化当前访问节点curNode为根; - 使用循环迭代代替显式的递归调用; - 如果遇到叶子结点就为其设立相应的前后向索引关系; - 对于非叶节点同样要检查其左右子树是否存在未被连接的部分并加以补充完善直到整个流程结束为止。 下面是Python版本的具体代码示例用于演示如何基于上述原则执行后列下的中线索化: ```python class TreeNode: def __init__(self, val=None): self.val = val self.leftChild = None self.rightSibling = None self.lTag = 0 self.rTag = 0 def inorderThread(root): prev = None def threadNodes(node): nonlocal prev if node is not None: # Traverse the left subtree first. threadNodes(node.leftChild) # Process this node (create threads). if node.leftChild is None and prev is not None: node.leftChild = prev node.lTag = 1 if prev is not None and prev.rightSibling is None: prev.rightSibling = node prev.rTag = 1 prev = node # Finally traverse the right subtree. threadNodes(node.rightSibling) threadNodes(root) ``` 此函数接受一个代表二叉树根部的对象,并对其应用中线索化过程。这里采用了一个内部辅助函数`threadNodes()`来进行具体的线索设定工作,同时借助外部变量`prev`记录上一次访问过的节点以便正确建立双向联系[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值