【算法】二叉树、N叉树先序、中序、后序、BFS、DFS遍历的递归和
? ? ? ? 本文总结了刷LeetCode过程中,有关树的遍历的相关代码实现,包括了二叉树、N叉树先序、中序、后序、BFS、DFS遍历的递归和迭代实现。这也是解决树的遍历问题的固定套路。
1 public void preorder(TreeNode root) { 2 if (root == null) { 3 return; 4 } 5 res.add(root.val); 6 preorder(root.left); 7 preorder(root.right); 8 } ? (2)中序 inorder(TreeNode root) { 3 inorder(root.left); inorder(root.right); 8 } ? (3)后序 postorder(TreeNode root) { 2 } postorder(root.left); postorder(root.right); res.add(root.val); 8 } ? 2、迭代模板:显式使用栈 1 2 Deque<TreeNode> stack = new ArrayDeque<>(); 3 while(root !=null || !stack.isEmpty()) { 4 while(root != 5 stack.push(root); 6 res.add(root.val);//保存结果 7 root = root.left; 8 } 9 root = stack.pop(); 10 root = root.right; 11 } 12 } ? (2)中序 2 Deque<TreeNode> stack = 3 4 stack.push(root); 6 root = 7 } 8 root = 9 res.add(root.val);10 root =12 } ? (3)后序。先序是根——左——右,而后序是左-右-根,可以将先序改成根-右-左,然后将结果反转。如下代码对比先序的代码: 3 7 root = root.right;注意这里和先序、中序的差别 root.left(); } 12 Collections.reverse(res);将前面的结果反转 13 } ? ? ? ?当然,上面这种方法比较间接,借助于先序遍历的理解。下面采用一种直接的迭代方式: 3 TreeNode preNode = new TreeNode();该节点用于保存前一个出栈的节点 4 while (root != 5 将当前节点的左子树节点一次入栈 6 8 root = 9 } 10 root = stack.peek(); 11 当前节点没有右孩子了,或者其右孩子已经出栈了,则当前节点也出栈 12 if (root.right == null || root.right == preNode) { 13 root =14 res.add(root.val);15 preNode = root; 记录本次刚输出的节点 16 root = 17 } else { 18 当前节点还有右孩子,且其右孩子还没有出栈,则先处理其右孩子 19 root =20 21 22 } ? 二、N叉树的先序与后序遍历 2 3 4 5 res.add(root.val); 6 if (root.children != 7 for (int i = 0; i < root.children.size(); i++ dfs(root.children.get(i)); 10 11 } ? (2)后序 3 5 postorder(root.children.get(i)); 8 res.add(root.val);9 } ? 2、迭代模板 preorder(Node root) { 2 Deque<Node> stack = new ArrayDeque<>(); BFS使用队列,这里使用栈 3 stack.push(root); 4 while (! 5 root = 6 res.add(root.val); 7 int childCount = root.children == null ? 0 : root.children.size(); 8 这里需要注意孩子节点入栈的顺序 9 int i = childCount - 1; i >= 0; i-- stack.push(root.children.get(i)); 12 13 } ? (2)后序。先序是根——左——右,而后序是左-右-根,可以将先序改成根-右-左,然后将结果反转。如下代码对比先序的代码: postorder(Node root) { 2 List<Integer> result = new ArrayList<> 3 Deque<Node> stack = 5 6 root = 7 result.add(root.val);还入栈的顺序正好和先序遍历相反 10 int i = 0; i < childCount; i++13 14 将结果反转 15 Collections.reverse(result); 16 for (Integer i:result) { 17 System.out.print(i); 18 19 } ? ? ? ?目前还没有找到类似二叉树直接后序遍历的方法 ? 三、树的BFS(广度优先搜索)和DFS(深度优先搜索)实现模板 bfs(Node root) { 2 Queue<Node> queue = new LinkedList<> queue.offer(root); queue.isEmpty()) { queue.poll(); queue.addAll(root.children);//这里的addAll后,root的children会从左往右依次入队。这一点Deque实现的栈正好相反,这一点需要注意 11 } ? (2)DFS ? 四、图的BFS和DFS遍历模板 ? ? ? ? 树是图的一种特殊情况,相比于树而言图中可能出现环,所以在遍历的时候可能重复访问。所以树的BFS和DFS实现需要在树的基础上维护一个Set来避免访问重复的节点即可。 ? 1、BFS graphyBfs(Node root) { 5 Set<Node> visitedSet = new HashSet<>(); 维护一个set,保存已经访问过的节点 6 Queue<Node> queue = queue.offer(root); 8 9 root =10 visitedSet.add(root);保存每个已经输出的节点 11 res.add(root.val);if (root.children == 13 14 15 16 Node tmpNode = root.children.get(i); 17 if (!visitedSet.contains(tmpNode)) {已经输出过的节点,则不用再加入 queue.offer(tmpNode); 19 } 22 } ? 2、DFS ? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- ios – 在App Store上提交应用程序
- 循序渐进PostgreSQL FAQ之安装篇
- JavaScript正则方法replace实现搜索关键字高亮显示
- 如何让WKWebView在swift和macOS App中工作
- C#程序中session的基本设置示例及清除session的方法
- ruby – 任何适用于Erlang的RSpec工具?
- ruby-on-rails – 在Rails中测试分段/生产环境的最佳方式是
- 仿百度,豆瓣读书文库阅读器
- React和ES6(二)--ES6的类和ES7的property initializer
- Flex之旅:第二部分:容器与布局(4)--- callLater()方法的使