二叉树 - DFS与BFS
二叉树 - DFS与BFS
深度优先遍历 (DFS
Depth First Search
) 就是一个节点不到头(叶子节点为空) 不回头 广度有点遍历(BFS
Breadth First Search
) 就是一层一层输出 , 输出到最下层的叶子节点, 为空的时候结束
其中深度遍历就是我们所说的 先序遍历 中序遍历 后序遍历 , 先中后指的是根节点输出的时机,先就是根左右
数据结构如下, 全文都是
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
输出要求
List<Integer> search(TreeNode root) {
// do 需要返回一个数组
}
测试数据
TreeNode root = new TreeNode(1);
TreeNode left = new TreeNode(2);
TreeNode right = new TreeNode(3);
root.left = left;
root.right = right;
left.left = new TreeNode(4);
left.right = new TreeNode(5);
right.left = new TreeNode(6);
1. DFS
1. 递归实现
递归实现代码相当之简单 , 所以很容易写, 就算不会也能记忆下来
1. 先序遍历
private List<Integer> preOrder(TreeNode root) {
if (null == root) return Collections.emptyList();
List<Integer> list = new ArrayList<>();
recursion(list, root);
return list;
}
// 递归
private void recursion(List<Integer> list, TreeNode root) {
if (null == root) return;
// 根
list.add(root.val);
// 左
recursion(list, root.left);
// 右
recursion(list, root.right);
}
2. 中序遍历
private List<Integer> midOrder(TreeNode root) {
if (null == root) return Collections.emptyList();
List<Integer> list = new ArrayList<>();
recursion(list, root);
return list;
}
private void recursion(List<Integer> list, TreeNode root) {
if (null == root) return;
recursion(list, root.left);
// 调换到中间
list.add(root.val);
recursion(list, root.right);
}
3. 后序遍历
private List<Integer> aftOrder(TreeNode root) {
if (null == root) return Collections.emptyList();
List<Integer> list = new ArrayList<>();
recursion(list, root);
return list;
}
private void recursion(List<Integer> list, TreeNode root) {
if (null == root) return;
recursion(list, root.left);
recursion(list, root.right);
// 调换到最后
list.add(root.val);
}
2. 递归执行流程
三种流程基本都差不多
好多人对于递归并不了解, 执行流程 , 我们知道方法的出栈需要一个return, 所以递归就是在找这个 , 就拿我们上面说的那个先序遍历为例子吧 .
3. 非递归实现(很重要)
递归的坏处就是 , 出入栈消耗大量的内存, 每一次方法的调用都会保存大量的变量, 多以对于遍历来说并不好 ,
非递归遍历的实现 , 基于栈的实现, 对于遍历节点保存在栈中, 出入栈 , 主要利用栈的后进先出的特性 , 很好的保证了, 后进的优先遍历 .
1. 先序遍历
非递归实现先序遍历
private List<Integer> preOrderUnRecursion(TreeNode root) {
if (null == root) return Collections.emptyList();
List<Integer> list = new ArrayList<>();
// 栈
LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
// 压栈
stack.push(root);
while (stack.size() > 0) {
// 出栈
TreeNode node = stack.pop();
TreeNode right = node.right;
if (null != right) {
stack.push(right);
}
TreeNode left = node.left;
if (null != left) {
stack.push(left);
}
list.add(node.val);
}
return list;
}
2. 中序遍历
这个实现就比较麻烦了 , 因为先序遍历, 根节点有先天的优势可以先出去 ,所以很
private List<Integer> midOrderUnRecursion(TreeNode root) {
if (null == root) return Collections.emptyList();
List<Integer> list = new ArrayList<>();
// 栈
LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
// 压栈
stack.push(root);
while (stack.size() > 0) {
// 出栈
TreeNode node = stack.pop();
TreeNode right = node.right;
TreeNode left = node.left;
if (null != right) {
node.right = null;
stack.push(right);
}
// 重复入栈 , 是因为根节点不是最先出来的
if (null != right || null != left) {
stack.push(node);
}
if (null != left) {
node.left = null;
stack.push(left);
}
if (null == left && null == right) {
list.add(node.val);
}
}
return list;
}
3. 后序遍历
private List<Integer> aftFirstSearchUnRecursion(TreeNode root) {
if (null == root) return Collections.emptyList();
List<Integer> list = new ArrayList<>();
// 栈
LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
// 压栈
stack.push(root);
while (stack.size() > 0) {
// 出栈
TreeNode node = stack.pop();
TreeNode right = node.right;
TreeNode left = node.left;
if (null != right || null != left) {
stack.push(node);
}
if (null != right) {
node.right = null;
stack.push(right);
}
if (null != left) {
node.left = null;
stack.push(left);
}
if (null == left && null == right) {
list.add(node.val);
}
}
return list;
}
4.非递归实现流程图
1. 先序遍历
2. 中序遍历和后序遍历一样
流程从左往右, 从上往下看 .
2. BFS
广度优先遍历就是一层 一层遍历 , 同一层, 从左到右输出,
基于队列实现的 , FIFO特性 , offer 和 poll , 操作
代码实现
private List<Integer> breadthFirstSearch(TreeNode root) {
if (null == root) return Collections.emptyList();
ArrayList<Integer> list = new ArrayList<>();
LinkedList<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (queue.peek() != null) {
TreeNode poll = queue.poll();
TreeNode left = poll.left;
if (null != left) {
queue.offer(left);
}
TreeNode right = poll.right;
if (null != right) {
queue.offer(right);
}
list.add(poll.val);
}
基本流程图
3. 求树的深度
利用树的先序遍历递归进行求树的深度
private int countDepth(TreeNode root) {
if (null == root) return 0;
int left = countDepth(root.left);
int right = countDepth(root.right);
return left >= right ? left + 1 : right + 1;
}
4. 求数的节点个数
也是递归遍历
private int countNode(TreeNode root) {
if (null == root) return 0;
return countNode(root.left) + countNode(root.right)+1;
}
二叉树 - DFS与BFS的更多相关文章
- UVA 548.Tree-fgets()函数读入字符串+二叉树(中序+后序遍历还原二叉树)+DFS or BFS(二叉树路径最小值并且相同路径值叶子节点权值最小)
Tree UVA - 548 题意就是多次读入两个序列,第一个是中序遍历的,第二个是后序遍历的.还原二叉树,然后从根节点走到叶子节点,找路径权值和最小的,如果有相同权值的就找叶子节点权值最小的. 最后 ...
- Clone Graph leetcode java(DFS and BFS 基础)
题目: Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. ...
- 数据结构(12) -- 图的邻接矩阵的DFS和BFS
//////////////////////////////////////////////////////// //图的邻接矩阵的DFS和BFS ////////////////////////// ...
- 数据结构(11) -- 邻接表存储图的DFS和BFS
/////////////////////////////////////////////////////////////// //图的邻接表表示法以及DFS和BFS //////////////// ...
- 在DFS和BFS中一般情况可以不用vis[][]数组标记
开始学dfs 与bfs 时一直喜欢用vis[][]来标记有没有访问过, 现在我觉得没有必要用vis[][]标记了 看代码 用'#'表示墙,'.'表示道路 if(所有情况都满足){ map[i][j]= ...
- 图论中DFS与BFS的区别、用法、详解…
DFS与BFS的区别.用法.详解? 写在最前的三点: 1.所谓图的遍历就是按照某种次序访问图的每一顶点一次仅且一次. 2.实现bfs和dfs都需要解决的一个问题就是如何存储图.一般有两种方法:邻接矩阵 ...
- 图论中DFS与BFS的区别、用法、详解?
DFS与BFS的区别.用法.详解? 写在最前的三点: 1.所谓图的遍历就是按照某种次序访问图的每一顶点一次仅且一次. 2.实现bfs和dfs都需要解决的一个问题就是如何存储图.一般有两种方法:邻接矩阵 ...
- 数据结构基础(21) --DFS与BFS
DFS 从图中某个顶点V0 出发,访问此顶点,然后依次从V0的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和V0有路径相通的顶点都被访问到(使用堆栈). //使用邻接矩阵存储的无向图的深度 ...
- dfs和bfs的区别
详见转载博客:https://www.cnblogs.com/wzl19981116/p/9397203.html 1.dfs(深度优先搜索)是两个搜索中先理解并使用的,其实就是暴力把所有的路径都搜索 ...
随机推荐
- 什么是redis事务
一.什么是redis事务? 可以一次性执行多条命令,本质上是一组命令的集合.一个事务中的所有命令都会序列化,然后按顺序地串行化执行,而不会被插入其他命令 二.Redis 事务可以做什么? 一个队列中, ...
- PTA的Python练习题(五)
昨天耽搁了一天,今天继续 从 第3章-5 字符转换 开始 1. a=input() b="" for i in a: ': b=b+iprint(int(b))#(写成b=i+b ...
- P1017进制转化
P1017进制转化 也不知道为啥,这么简单的题困扰了我这么长时间 #include<cstdio> using namespace std; int m; //被除数= 除数*商 + 余数 ...
- Java记录4--string
1.toString所有的类都默认自动继承了Objiect类 2.Object类中的toString方法返回的时类的名字和该哈希表码组成的一个字符串, System.out.println(类对象名) ...
- Python学习笔记007
赋值运算符 num+=1 num=num+1 num-=1 num=num-1 num*=2 num=num*2 num/=2 num=num/2 num//=2 num=num//2 num%=2 ...
- eclipse启动时权限不够的问题
eclipse启动时权限不够的问题 2009年04月28日 19:19:00 tomey21 阅读数 1445 安装好后每次都要用root权限运行,比较郁闷,摸索了一下,修改一下相关目录的权限就可 ...
- matplotlib 柱状图 Bar Chart 样例及参数
def bar_chart_generator(): l = [1,2,3,4,5] h = [20, 14, 38, 27, 9] w = [0.1, 0.2, 0.3, 0 ...
- 「AMPPZ2014」The Captain
传送门: 这是一道bzoj权限题 Luogu团队题链接 解题思路 直接连边的话边数肯定会爆炸,考虑减少边数. 我们画出坐标系,发现一个东西: 对于两个点 \(A,B\),\(|x_A-y_A|\) 可 ...
- linux安装jdk并设置环境变量(看这一篇文章即可)
1.查看linux位数 查看linux是32位还是64位,影响需要下载JDK的版本 系统位数 jdk位数 x86(32位) 32位 x86_64(64位) 32位 64位 在linux命令输入: ...
- 112、Java中String类之字符串文本拆分为指定的个数
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...