层序遍历一棵树在工程化的实践中有着广泛的应用,比如我们遍历一个json,如下的json我们看到有两层。首先遍历第一层,遍历完成后再遍历第二层author节点
下的内容,遍历html树的时候也会存在这种情况。
{
"product": "fileup跨平台局域网文件分享",
"website": "http://fileup.marsdl.com",
"author": {
"username": "chenrui",
"age": "250"
}
}
分步查看层序遍历算法的实现
对如下的一棵树进行层序遍历,根据树的根节点存入队列中,然后从队列中获取队列的第一个节点并且访问,并将其左右节点和右节点存放至队列中。依次进行下去。
如下图,开始访问一棵树的初始化操作,队列的第一个节点就是树的第一个节点根节点
。
遍历完html节点
节点后从队列移除,将html节点
的左子节点
与右子节点
放入队列中。
进行下一个节点的访问,下一个节点的访问就是访问队列中第一个节点;当前队列的第一个节点是head节点
,访问head节点
并从队列的移除,然后将head节点
的左子节点
与右子节点
放入队列中。
而后再次下一个节点访问,查看队列中的第一个节点,此时第一个节点为body节点
。访问body节点
并将其左子节点
与右子节点
放入队列中。依次这种方式进行下去,直到队列为空即为遍历完成。
总的来说层序遍历分为三个步骤
- 初始化将树的根节点放入初始化的队列;
- 依次获取队列中第一个节点来进行二叉树的遍历,并把访问节点的
左子节点与右子节点
放入队列中; - 队列中没有数据时,这标志着这棵树遍历完成。
层序遍历的代码
public static void sequenceTraverse(Node node) {
//初始化将树的根节点放入初始化的队列
Queue<Node> nodeQueue = new LinkedList<>();
nodeQueue.offer(node);
//队列中没有数据时,这标志着这棵树遍历完成
while (!CollectionUtils.isEmpty(nodeQueue)) {
//依次获取队列中第一个节点来进行二叉树的遍历
Node currentNode = nodeQueue.poll();
System.out.println(currentNode.value);
//把访问节点的`左子节点与右子节点`放入队列中
if (currentNode.leftChild != null) {
nodeQueue.offer(currentNode.leftChild);
}
if (currentNode.rightChild != null) {
nodeQueue.offer(currentNode.rightChild);
}
}
}
生产实践中的多叉树层序遍历
在生产实践中我们会遇到多叉树,像实际的html内容与实际的json文件产生的树都是多叉树。没法像二叉树那种判断是否有左孩子,右孩子,如下的代码有直接对应的左孩子与右孩子将不适用。
if (currentNode.leftChild != null) {
nodeQueue.offer(currentNode.leftChild);
}
if (currentNode.rightChild != null) {
nodeQueue.offer(currentNode.rightChild);
}
改用如下的伪代码方式,比如访问某一个节点时,需要将其所有的孩子节点
放入到队列
中去。isChildrenNotNull()
是伪代码判断当前节点是否有孩子节点,children()
所有的孩子节点。
if (currentNode.isChildrenNotNull()) {
nodeQueue.offer(currentNode.children());
}
总结:发现到如果理解了层序遍历的本质,对工程中的多叉树只是判断条件稍微改变,其层序遍历的思想没有改变。层序访问多叉树的伪代码。
public static void sequenceTraverse(Node node) {
//初始化将树的根节点放入初始化的队列
Queue<Node> nodeQueue = new LinkedList<>();
nodeQueue.offer(node);
//队列中没有数据时,这标志着这棵树遍历完成
while (!CollectionUtils.isEmpty(nodeQueue)) {
//依次获取队列中第一个节点来进行二叉树的遍历
Node currentNode = nodeQueue.poll();
System.out.println(currentNode.value);
//判断当前节点是否存在孩子节点,如果存在全部加入到队列中
if (currentNode.isChildrenNotNull()) {
nodeQueue.offer(currentNode.children());
}
}
}