二叉树遍历系列总结+递归/迭代的统一写法
本文提供二叉树 前中序 三种遍历方式的 递归和迭代 统一写法。递归写法很简单
在面试中不足以获得面试官的青睐,应该重点掌握迭代写法
一、题目
144. 二叉树的前序遍历
94 . 二叉树的中序遍历
145. 二叉树的后序遍历
二、分析:DFS/BFS 与树的遍历
-
有两种通用的遍历树的策略:
-
深度优先搜索(DFS)
在这个策略中,我们采用深度作为优先级,以便从跟开始一直到达某个确定的叶子,
然后再返回根到达另一个分支。深度优先搜索策略又可以根据根节点、左孩子和右孩子的相对顺序
被细分为前序遍历,中序遍历和后序遍历。 -
宽度优先搜索(BFS)
我们按照高度顺序一层一层的访问整棵树,高层次的节点将会比低层次的节点先被访问到。
对应数的层次(层序遍历)
-
-
*****五星重点
- 前中后序遍历的递归和迭代写法 本质上对应DFS的递归写法和显示调用栈的写法
- 递归解决方案的优点是它更容易实现。 但是,存在一个很大的缺点:如果递归的深度太高,你将遭受堆栈溢出。 在这种情况下,推荐使用显式栈实现 DFS(有时也可以用BFS)。
- 显式栈实现 DFS逻辑与递归解决方案完全相同。 但我们使用 while 循环和栈来模拟递归期间的系统调用栈
- DFS的两种方式的解题模板参考:深度优先搜索DFS_图文详解_Java代码_leetcode刷题模板
- DFS模板I—递归写法
/* * Return true if there is a path from cur to target. */ boolean DFS(Node cur, Node target, Set<Node> visited) { return true if cur is target; for (next : each neighbor of cur) { if (next is not in visited) { add next to visted; return true if DFS(next, target, visited) == true; } } return false; }
- DFS模板II—显示调用栈写法
/* * Return true if there is a path from cur to target. */ boolean DFS(int root, int target) { Set<Node> visited; Stack<Node> s; //额外注意:BFS 这里使用的是queue队列。 add root to s; while (s is not empty) { Node cur = the top element in s; return true if cur is target; for (Node next : the neighbors of cur) { if (next is not in visited) { add next to s; add next to visited; } } remove cur from s; } return false; }
链接:https://leetcode-cn.com/problems/binary-tree-preorder-traversal/solution/er-cha-shu-de-qian-xu-
三、递归的写法
递归写法只需要调整list添加节点值 和 左右子树递归的顺序即可。
前序: 根 左 右 :list.add(root.val) -> dfs(左子树) -> dfs(右子树)
中序: 左 根 右 :dfs(左子树) -> list.add(root.val) -> dfs(右子树)
后序: 左 右 根 :dfs(左子树) -> dfs(右子树) -> list.add(root.val)
- 1.前序遍历
class Solution { public List<Integer> preorderTraversal(TreeNode root) { //创建list List<Integer> res = new ArrayList(); //递归调用 dfs(root,res); //返回结果 return res; } private void dfs(TreeNode root, List<Integer> list){ if(root != null ){ //1.先添加root值 list.add(root.val); //2.递归左子树 dfs(root.left,list); //3.递归右子树 dfs(root.right,list); } /* 【另一种写法】 //递归终止条件, base case if(root == null) return; //先遍历根节点, 直接添加节点值 list.add(root.val);//前序遍历 根 左 右 //递归左子树 //if(root.left != null) recur(root.left,list); //递归右子树 //if(root.right != null) recur(root.right,list); */ } }
- 2.中序遍历
class Solution { public List<Integer> inorderTraversal(TreeNode root) { //创建list List<Integer> res = new ArrayList(); //递归调用 dfs