1 线索化二叉树的使用背景
二叉树的遍历,以中序遍历为例,参考下图1,需要频繁的递归和出入栈,如当节点没有右儿子,后继节点其实没有那么容易判断,如图2的E点,而且如果不通过递归和栈的性质将很难获得其后继, 这可能会占用额外的内存,而且也不容易理解。
线索是一种对二叉树的操作,意思是对二叉树进行线索化,其目的是使线索化后的二叉树具有方便被遍历的特点,即不使用递归和栈也可以对线索化之后的树进行中序遍历。
2 二叉树线索化的思路
问题出在缺左右孩子的节点上,而且我们看到其实这个空的指针域其实是可以利用起来的。
所以,在对一棵二叉树进行中序遍历(不限于中序遍历)的过程中, 我们对其进行线索化时这样规定的,如果某一节点的左孩子为空,那么将其左孩子指向该节点的前驱, 如果某一节点的右孩子为空,那么再将其右孩子指向该节点的后继。
特别地,在设计代码时,我们需要区分前驱节点、后继节点和左右孩子,可以定义一个节点的属性rightType和leftType,如果是正常的左右孩子就记为0,否则为1以示区别。
3 线索化二叉树的遍历
线索化二叉树可以不用原先的遍历方式,即不断地递归和出栈回溯,而是利用线索去用线性的遍历方式来复现二叉树的中序遍历(不限于中序),这里可以对照前面图1中序遍历。
思路:①当左子节点是leftType==0的节点(有左子节点),循环取左子节点 ==> 相当于 左子节点不为空时,取左子节点并递归(中序)遍历
②输出当前节点 ==> 相当于 输出当前节点
③当右子节点是rightType=1的节点时(没有右子节点),循环取右子节点,并输出 ==> 相当于 (没有右子节点)回溯出栈
④(有右子节点)取右子节点,进入下个while循环 ==> 相当于 右子节点不为空时,取右子节点并递归(中序)遍历
while (node != null) {
//1
while (node.getLeftType() == 0) {
node = node.getLeft();
}
//2
System.out.println(node);
//3
while (node.getRightType() == 1) {
// 获取当前节点的后继节点
node = node.getRight();
System.out.println(node);
}
//4
node = node.getRight();
}
4 二叉树线索化的意义
线索二叉树就是将二叉树中空的指针域利用了起来,用来保存遍历过程中前驱结点和后继结点的信息。而二叉树的遍历其实就是一个将树这种一对多的非线性结构转化成一个一对一的线性结构的过程。