在二叉树中,假设有n个叶子节点,那会产生n+1个空节点,而线索化二叉树就是将这些空节点利用起来,建立指向该节点的前驱后者后继节点的指针。
虽然说可以有三种遍历的方式来线索化二叉树,但是在实际应用中一般都是使用中序线索化,具体原因在后面说。
在线索化二叉树中, 因为要分清左右节点是前驱/后继还是左右子树,所以需要对节点做一些修改,添加上一个标记来表示具体的节点,
下面来看一个具体的例子来了解如何进行中序线索化
首先是可以写出这棵树的中序遍历,BCAED,然后按照该顺序一个节点一个节点地判断。
递归算法如下,调换顺序可以得到前序和后序的线索化。
但其中主要起作用的是函数中的三个if语句
1.若当前节点的左子树为空,就表明可以指向前驱节点,所以tag为1,lchild为pre节点
2.若当前节点的右子树为空,则令右tag为1,表示可以连接后继节点
3.若pre节点存在并且pre节点的右tag为1,则表示pre节点的后继节点是当前节点,所以令pre的右子树为当前节点
4.令当前节点为pre节点,为下一个循环做准备
也就是说,要处理前驱节点可以在当前循环中解决,但是要处理后继节点则只能在下一次循环中解决, 因为我们设置的辅助节点保存的是上一个遍历的节点,所以当要处理后继节点的时候,只能在下一次循环中对pre节点进行操作。
该树的线索化结果如下
接下来是中序线索化的非递归算法
其实实现非常简单,我们只需要在非递归的遍历中,将输出节点的数据修改成以上的字段就可以实现非递归的中序线索化,下面来看看代码实现
线索化的目的是为了更方便寻找某一个节点的前驱和后继节点,所以我们还需要两个简单的函数来获得它。
以寻找前驱节点为例,如果左tag为1,表明左子节点就是前驱节点
否则,就代表一定存在左子树,则我们要在左子树里面,找到左子树在中序遍历的最后一个节点,也就是右下的节点,这个时候直接返回该节点即可。
寻找后继节点同理,不再赘述。
最后就是中序线索化的遍历了,这个也是整个线索化中最简单的部分了,所以只附上代码: