加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

【算法】二叉树、N叉树先序、中序、后序、BFS、DFS遍历的递归和

发布时间:2020-12-14 04:46:16 所属栏目:百科 来源:网络整理
导读:? ? ? ? 本文总结了刷LeetCode过程中,有关树的遍历的相关代码实现,包括了二叉树、N叉树先序、中序、后序、BFS、DFS遍历的递归和迭代实现。这也是解决树的遍历问题的固定套路。 一、二叉树的先序、中序、后序遍历 ? 1、递归模板 ? (1)先序 1 public void

? ? ? ? 本文总结了刷LeetCode过程中,有关树的遍历的相关代码实现,包括了二叉树、N叉树先序、中序、后序、BFS、DFS遍历的递归和迭代实现。这也是解决树的遍历问题的固定套路。


一、二叉树的先序、中序、后序遍历
? 1、递归模板
? (1)先序

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)先序 。也可以使用后文的DFS实现

 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叉树的先序与后序遍历
? 1、递归模板
? (1)先序

 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、迭代模板
? (1)先序。即下文中DFS的实现

 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(深度优先搜索)实现模板
? 1、递归实现
? (1)BFS
? ? ? ? ? 一般来说不能使用递归来实现BFS,因为BFS使用的时队列实现,而递归使用的是栈实现。
? (2)DFS
? ? ? ? ? 普通的N叉树的DFS包括先序遍历和后序遍历,它们的递归实现和前文一致。如果是二叉树,还有中序遍历,递归实现和前文一致。
? 2、迭代实现
? (1)BFS。即按层次来遍历

 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
? ? ? ?迭代方式、递归方式,都维护一个set来保存已经访问过的节点,在输出节点时保存到set中,在添加节点时添加去重操作即可。

?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读