一、线索化二叉树的相关原理:
1.线索化二叉树的原理
对于二叉树来说,一个包含n个节点的二叉树的叶子节点会包含(2n - (n - 1) = n + 1)个空指针是指向null的,即指针资源被浪费。为了实现指针的有效利用,将未指向节点的指针添加两种功能,即左节点如果为空,将其指向当前遍历顺序的前一个节点(前驱节点),右节点如果为空,将其指向当前遍历顺序的下一个节点(后继节点)。这是实现二叉树线索化的主要思想。
这里就对二叉树保存遍历的前一个节点的功能提出了要求,不同于普通二叉树,需要一个pre来保存遍历时的前一个节点。
2.对于线索化二叉树的遍历的原理
对已经线索化二叉树的遍历,首先得找到二叉树遍历的入口节点(对于前序是根节点,对于中序和后序是树最左边的子节点),然后根据遍历顺序,判断是按照遍历顺序走还是按照线索化的后的后继节点走。
这里提出了左右节点指向的区别功能。即指向的是子树还是前驱(后继)节点,需要对节点功能进行补充。
二、线索化二叉树的代码详解
1.前序二叉树线索化的原理
前序二叉树线索化,是按照当前节点->左子节点->右子节点的顺序来遍历的。所以处理的时候也应该按照此顺序来对二叉树进行处理。(其实,三种线索化主要是处理节点的顺序不同,对比三种线索化的代码即可知,本质没有太大区别)
前序线索化二叉树代码:
//二叉树前序线索化方法
public boolean threadPre()
{
if (this.root != null)
{
threadPre(root);
System.out.println("前序线索化成功!");
return true;
}
else
{
System.out.println("前序线索化失败!");
return false;
}
}
private void threadPre(HeroNode node)
{
//安全性判断
if (node == null)
{
return;
}
//前序顺序 当前节点 -> 左节点遍历 -> 右节点遍历
/*
处理当前节点
*/
//当前节点的左边,即处理前驱节点
if (node.getLeft() == null)
{
//左子节点为空,设置为前驱节点
node.setLeft(pre);
//说明左节点不是左子树,设置状态
node.setLeftStatus(false);
}
//上一个节点的右边,处理的是上一个的后继节点,因为无法知道当前节点的遍历顺序的下一个
if (pre != null && pre.getRight() == null) //pre为空 代表第一次进来root的左节点和右节点都为空
{
//在处理当前节点时,如果上一个节点的右节点还是空的,就要设置后继节点
pre.setRight(node);
//说明右节点不是左子树,设置状态
pre.setRightStatus(false);
}
//更新pre
pre = node;
/*
遍历左节点
*/
//不能让 左节点 已经连接前驱节点还是参与遍历
if (node.getLeftStatus())
{
//左节点遍历
threadPre(node.getLeft());
}
/*
遍历右节点
*/
//不能让 右节点 已经连接后继节点还是参与遍历
if (node.getRightStatus())
{
//右节点遍历
threadPre(node.getRight());
}
}