线索二叉树(中序、先序、后续的前驱和后继)

线索二叉树基本概念

遍历二叉树可以按一定规则得到一个线性序列(先序序列、中序序列、后序序列)。这些序列除头尾之外,都有且仅有一个前驱和一个后继。

当遍历二叉树时,只能得到结点的左右孩子信息,而不能直接得到结点的前驱和后继信息,只能从根节点遍历得到,由此引入线索二叉树。

线索二叉树就是为了加快查找结点前驱和后继的速度。

规定:
若结点有左孩子,则 lchild 域指向其左孩子,否则, lchild 域指向其前驱;
若结点有右孩子,则 rchild 域指向其右孩子,否则, rchild 域指向其后继;

为了避免混淆,在原来的结点基础上增加两个表示域:

lchildltagdatarchildrtag

ltag = 0:lchild 域指向结点左孩子
ltag = 1:lchild 域指向结点前驱

rtag = 0:rchild 域指向结点右孩子
rtag = 1:rchild 域指向结点后继

以这种结点结构构成的二叉链表作为二叉树的存储结构,叫做线索链表
其中指向结点前驱和后继的指针,叫做线索
加上线索的二叉树,叫做线索二叉树
对二叉树以某种次序遍历使其变为线索二叉树的过程,叫做线索化,线索化的过程就是在遍历的过程中修改空指针的过程。

构造线索二叉树

中序线索二叉树

中序线索二叉树,就是非空二叉树进行中序线索化之后所得到的。

中序序列:a+b*c-d-e/f
在这里插入图片描述
树中所有叶子结点的右链是线索,则右链直接指向了结点的后继;b结点的后继为 * 。
非叶子结点右链是指针,无法得到后继信息。

根据中序遍历的规律知:

结点的后继:遍历其右子树时访问的第一个结点,即右子树中最左下的结点;

结点的前驱:若没有左孩子其左标志为 1 ,则左链为线索,指向其前驱 ;否则,遍历左子树时最后一个访问的结点(左子树中最右下的结点)位其前驱。

先序线索二叉树

先序序列:-+a*b-cd/ef
在这里插入图片描述
黄色结点有左孩子,无法记录其前驱结点,则找不到其前驱结点。

根据先序遍历的规律知:

结点的后继:若有左孩子,则左孩子就是其后继,若没有左孩子但有右孩子,则右孩子就是其后继,若是叶子结点右标志为1,则右链为线索,指向其后继;

结点的前驱:若没有左孩子其左标志为 1 ,则左链为线索,指向其前驱 ;否则,有左孩子,无法存储左链,不能直接找到其前驱结点。

后序线索二叉树

后序序列:abcd-*+ef/-
在这里插入图片描述
黄色结点有左孩子,无法记录其前驱结点,则找不到其前驱结点。

根据后序遍历的规律知:

结点的后继:
1、若结点是二叉树的根,则后继为空;
2、若结点是其双亲的右孩子,或是其双亲的左孩子且其双亲没有右子树,则其后继就是其双亲结点;
3、若结点是其双亲的左孩子,且其双亲有右子树,则其后继为双亲的右子树上按后序遍历列出的第一个结点

结点的前驱:若没有左孩子其左标志为 1 ,则左链为线索,指向其前驱 ;否则,有左孩子,无法存储左链,不能直接找到其前驱结点。

线索二叉树是一种对二叉搜索的一种增强,它除了存储常规的节点信息外,还额外添加了一些指针,使得遍历过程中可以不需要访问实际的前驱后继节点就能确定下一个待访问节点。主要有三种类型的线索前驱线索、当前节点后继线索。 1. **中线索化**: 中线索二叉树在中遍历时,对于每个节点,它的左孩子线索指向其左兄弟(如果存在),如果没有左兄弟,则指向NULL;右孩子线索指向其直接右子节点。 2. **线索化**: 线索化通常用于构建线索链表的开始。根节点的右孩子线索总是指向其第一个子节点,其他节点的左孩子线索指向其父节点,右孩子线索指向其直接右子节点。 3. **遍历**: 从根节点开始,按照“左->当前节点->右”的顺访问节点,并利用线索判断下一步访问谁。 4. **中遍历**: 遵循“当前节点->左->右”的顺,通过线索找到左孩子的后继节点。 为了编写程表示这种结构,你可以使用递归或迭代的方式。这里提供一个简单的Python示例,假设有一个基本的二叉树节点定义: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right self.prev = None # 前驱线索 self.next = None # 后续线索 # 中线索化的函数示例 def inorder_traversal_with_links(root): if root is not None: stack = [] curr = root while True: while curr is not None: stack.append(curr) curr = curr.left if not stack: break node = stack.pop() print(node.val) # 访问节点 curr = node.right # 跳转到右子节点(如果有) if curr is not None: node.next = curr # 设置后续线索 curr.prev = node # 初始化并线索化一个例子 root = ... # 初始化一个二叉树 inorder_traversal_with_links(root) ``` 注意,这只是一个基础示例,实际应用中可能需要处理更多边界条件细节。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值