博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
树的层次遍历的几种方法
阅读量:5948 次
发布时间:2019-06-19

本文共 2481 字,大约阅读时间需要 8 分钟。

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

 

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

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

 

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

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

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

 

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

queue = [node]  // 新建一个队列,并将根节点放入队列while queue.length != 0    item = 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 != 03     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 != 03     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更难点,需要有更强的逻辑思维能力。

 

转载于:https://www.cnblogs.com/simplepaul/p/6721687.html

你可能感兴趣的文章
批量删除用户--Shell脚本
查看>>
如何辨别android开发包的安全性
查看>>
Eclipse Java @Override 报错
查看>>
交换机之间的VLAN通信(trunk)
查看>>
heartbeat-gui
查看>>
关于一阶逻辑中实例化的可满足性问题
查看>>
cut命令用法讲解
查看>>
我的第一篇日志。
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
企业实战:mysql5.6数据库备份、恢复脚本
查看>>
CentOS7安装mysql
查看>>
RMB數字轉換中文
查看>>
基于rhel7.2的Zabbix平台搭建和部署(二)
查看>>
Html5本地存储和本地数据库
查看>>
JQ 循环切换DIV
查看>>
Android Fragment实践(二)
查看>>
centos 修改主机名立即生效和重启后也生效的方法
查看>>
Windows 64 位 mysql 5.7以上版本包解压安装
查看>>
知道双字节码, 如何获取汉字 - 回复 "pinezhou" 的问题
查看>>