数据结构1:中序线索化二叉树思考
private HeroNode pre = null;//在递归线索化,pre总是保留前一个结点
/**
*
* @param node 就是当前需要线索化的结点
*/
public void threadedNodes(HeroNode node){
//如果node == null,不能线索化
if(node == null){
return;
}
//(一)先线索化左子树
threadedNodes(node.getLeft());
//(二)线索化当前结点[有难度]
//处理当前结点的前驱结点
//以8结点来理解
//8结点.left = null,8结点的Lefttype = 1
if(node.getLeft() == null){
//让当前结点的左指针指向前驱结点
node.setLeft(pre);
//修改当前结点的左指针的类型,指向前驱结点
node.setLeftType(1);
}
//处理后继节点
if(pre != null && pre.getRight() == null){
//让前驱结点的右指针指向当前结点
pre.setRight(node);
//修改前驱结点的右指针类型
pre.setRightType(1);
}
//!!!每处理一个结点后,让当前结点是下一个结点的前驱结点
pre = node;
//(三)再线索化右子树
threadedNodes(node.getRight());
}
上面的(一)(三)就是在递归,分别进去左子结点、右子结点,这个好理解。重点是在第(二)个步骤,即线索化当前结点。
问题:为什么设置前驱结点的时候,直接node.setLeft(pre),而设置后驱结点的时候,不能直接node.setRight(……)呢?
自己解释:因为是中序线索化,即先进入左子树,再进行当前结点,再进入右子树。即考虑当前结点的时候左子树已经走过了,这个时候我更改左子树结点不影响后面递归的进行,故可以直接设node.setleft;但是右子树则不同,因为这个时候还没有进入右子树,我如果直接设置了node.setright(比如下图中10的后继节点是1),那么后面进入右子树递归的时候就进入了刚刚设置的结点(即下图中的1结点,那么后面又重新进入3 8 10 1……),这样递归就成为了死循环。
图自韩顺平老师课件
所以我们设置该结点的后继结点的时候不能在这一次递归中直接设置,而是通过pre记下当前结点,待我把右子树走过之后,再通过pre.setright来设置后继结点,这个时候因为node已经走到下一个递归里了,更改pre的后继节点已经不会造成影响。
如果大家想看一下递归是具体怎么走的,可以移步另一个陈平老师的视频(大约从第18分钟开始),不过就递归本质而言,老师们可能默认大家都知道,所以没解释为什么直接对当前结点设置setright不行。
图自陈平老师课件
兄弟们加油!