查找树的指定层级_树的层次遍历的几种方法

--------转自 每日一道算法题  公众号

树的遍历是一个基础问题,也有很多的实际应用,可以用来找到匹配的字符串、文本分词和文件路径等问题。

数的遍历有两个基本的方法:深度优先遍历 和 广度优先遍历 。

深度优先遍历又根据处理节点的顺序不同,可以分为:中序遍历、前序遍历和后序遍历。这些知识点也是深度优先遍历经常考察的。

广度优先遍历的考察在于层次遍历,比如需要我们按照层次输出一棵树的所有节点的组合(LeetCode 107),比如求一棵树的最左节点(LeetCode 513).这些

问题本质上都是考察的广度优先遍历。

如下代码是经典的广度优先遍历实现的方式,使用了队列的FIFO的方式,将所有暂未访问的节点存入一个队列,依次遍历。

queue = [node] //新建一个队列,并将根节点放入队列

while queue.length != 0item= queue.shift //弹出队列的头部元素

do_someting(item) //操作该节点:比如存入一个数组或者打印

queue.push(item.left) if item.left //将左子节点存入队列

queue.push(item.right) if item.right //将右子节点存入队列

但是只掌握了上面的遍历方法是不够的,层次遍历的难点在于 层次的比较 。也就是说,我们需要对不同层次的节点做 隔离。

--------------------------------------------正文---------------------------------------------------------------------------------------------------------------------------------------------

遍历技巧一: 数组长度做隔离

思路:

获取当前的队列的长度length,一次只遍历length个节点,后续加入的元素在下一次循环遍历。

伪代码如下:

1 queue = [node] //新建一个队列,并将根节点放入队列

2 while queue.lengh != 0

3 length = queue.length //获取当前队列的长度

4 while length > 0 //只弹出length 个节点

5 item = queue.shift //弹出队列的头部元素

6 do_something(item) //操作该节点:比如存入一个数组或者打印

7 queue.push(item.left) if item.left //将左子节点存入队列

8 queue.push(item.right) if item.right //将右子节点存入队列

9 length--

遍历技巧二:使用分隔符

思路

在不同的节点中间加入一个分隔符,遍历发哦分割几点的时候,停止当前遍历。

伪代码如下:

1 queue = [node] //新建一个队列,并将根节点放入到队列

2 while queue.lengh != 0

3 queue.push "$" //将分割符放入队列

4 while(true) //做一个无限循环

5 item = queue.shift //弹出队列的头部元素

6 break if item == '$' //如果当前的节点等于分隔符,说明该层已经遍历到了最右边

7 do_something(item) //操作该节点

8 queue.push(item.left) if item.left //将左子节点存入队列

9 queue.push(item.right) if item.right //将右子节点存入队列

遍历技巧三:使用深度优先搜索

思路:

用一个level字段来保存深度,在深度优先遍历的时候,判断一下当前结点的深度即可

伪代码如下:

1 ans = [] //用一个数组来保存值

2 level = 0 //根节点的level 是0

3 visit(node,ans,level)4

5

6 def visit(node,ans,level):7 return if node is null //如果节点为空,则返回8 //逻辑处理部分

9 if ans.lengh > level //说明之前访问过该层的节点

10 ans.[level].push node.val11 else //说明之前level没有访问过

12 ans.[level] =[node.val]13 visit (node.left, level +1,ans)14 visit (node.right, level +1,ans)

逻辑处理部分的代码还有一个需要注意的地方,比如LeetCode 107 需要求reverse后的结果,所以处理这一部分逻辑代码时,需要找到当前level对应的数组的position。

总结

树的难点在于树的构造,需要将一般性问题抽象成一棵树,需要定义好节点和路径。当我们构造好一棵树后,一般只需要遍历这棵树就能得到结果。所以树的遍历是一个基础问题。

其中分层遍历的技巧比dfs/bfs更难点,需要有更强的逻辑思维能力。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值