一、前言
多叉树一般用于解决回溯问题。
想必大家都学过二叉树,以及二叉树的深度优先遍历和广度优先遍历,我们思考:能不能将二叉树的DFS转化为多叉树的DFS?
二、多叉树的结构
多叉树的本质,就是一棵普通的树,比如下图:
如果忽略将来的变化,那么,这棵树可以认为是一个未满的4叉树。
由于多叉树代码实现比较复杂,在此不介绍。
三、从二叉树看多叉树
二叉树是非常特殊的,每一个节点,它只有2个子节点。并且,这两个节点可以直接拿到,即:
left指向左子节点,right指向右子节点。通过left、right就可以拿到它的左右节点。
多叉树是更加普遍的树结构,它满足树的层序性,满足最多一个父节点的性质。
四、二叉树的DFS,为什么不适用于多叉树?【以中序遍历为例】
我们知道,二叉树遍历满足口诀:“节点,左子树,右子树”。
链接为
二叉树中序遍历
如果为二叉树的节点,增加一条子树X,位于右子树的右边。
结构为【左子树,右子树,X子树】
此时,使用中序遍历的口诀,我们发现,子树X遍历不到。【每一层子树X都遍历不到】。
五、解决多叉树遍历问题
多叉树遍历问题的关键在于,由于语句的次序性,每一次只能访问一个节点。
解释:二叉树的递归函数A中,访问节点值的操作,只发生一次,然后将访问左右子节点值的操作,交给子递归函数A’。
即使多出一个子树X,也不会改变语句的次序性。
解决方案:二叉树访问节点Node后,将左右子节点的访问交给子递归函数,那么,也可以把X子树的访问,同样交给子递归函数。
伪代码:
void function(Node root){
// 如果节点为null,返回
if(node == null) return;
// 访问节点
print(root.val);
//依次访问左子、右子和X子树
function(root.left);
function(root.right);
function(root.X);
}
做完这一步,相信你对解决其它的多叉树遍历问题也有所了解。
然而,新问题出现了:
function函数,有指向性,直接拿到多叉树的第i个子树,然后遍历。
对于普遍的二叉树,这是没法做到的。
六、解决普遍多叉树,无指向性问题的两种方案
第一,定义节点顺序
既然无指向性,最简单的方案就是提供指向性。
比如对于4叉树,定义为:
第一个子节点fir,
第二个sec,
第三个thi,
第四个four。
这样,访问时就可以依次访问了。
当然,这种解决方案,不适用于外部复杂情况
第二,不考虑顺序,直接遍历子节点集合
如果多叉树提供一种方法,能够返回子节点集合。
那么,我们可以使用List存储子节点集合。
然后用foreach方法,遍历所有子树。
这种方案,使用时不考虑节点间的顺序性。
七、结语
我是蚊子码农,如有补充或者疑问,欢迎在评论区留言。个人的知识体系可能没有那么完善,希望各位多多指正,谢谢大家。