二叉树的基本特性和二叉树的几种基本操作的机制_算法基础:二叉树的遍历

二叉树是平时最常见的数据结构之一。

它属于树的一种,其中每个节点都不能有多余两个的儿子。

5f5826babb3aadc74954abbe1515f15f.png
二叉树

在面试或者平常做算法题时,如果遇到二叉树类的题目,基本都要借助到二叉树的遍历,下面就来介绍一下二叉树的几种常见遍历方式。

二叉树的遍历主要分为:深度优先遍历广度优先遍历

深度优先遍历

英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止。

二叉树的深度优先遍历主要有三种:前序遍历中序遍历后序遍历

下面我们以一道leetcode题来看看二叉树的深度优先遍历是如何实现的。

30ad9fae19650b2407795a5fb8678aee.png

递归

当遇到深度优先遍历时,首先想到的是递归,而此题采用递归算法来实现二叉树的中序遍历还是比较简单的,直接看代码:

class Solution {
    public List inorderTraversal(TreeNode root) {
        List res = new ArrayList();
        inorder(root, res);return res;
    }public void inorder(TreeNode root, List res) {if (root == null) {return;
        }
        inorder(root.left, res);
        res.add(root.val);
        inorder(root.right, res);
    }
}

上面的res.add(root.val);如果放在inorder(root.left, res);之前,就是前序遍历;如果放在inorder(root.right, res);之后,就是后序遍历。

tip:如果是二叉树,那中序遍历的结果将是一个升序数组。

迭代

还有一种方法是采用迭代,这就需要借助到另外一种数据结构-

其实上面的递归算法中,递归方法本身也属于栈,因此,我们可以在迭代方法中采用栈来代替递归。

首先,我们要清楚,中序遍历是先访问左子树,再访问自身,最后访问右节点。

所以,我们可以从根节点循环将左子树压入栈中,直到左子树为空,然后将左子树弹出的同时,再依次将右子树压入栈中。

这样就可以通过迭代来实现中序遍历。

下面看看代码是如何实现的:

class Solution {
    public List inorderTraversal(TreeNode root) {
        List res = new LinkedList<>();
        Deque deque = new LinkedList<>();while (root != null || !deque.isEmpty()) {// 循环将左子树压入栈中while (root != null) {
                deque.push(root);
                root = root.left;
            }
            root = deque.pop();
            res.add(root.val);
            root = root.right;
        }return res;
    }
}

广度优先遍历

英文缩写为BFS即Breadth FirstSearch。其过程检验来说是对每一层节点依次访问,访问完一层进入下一层,直到最后一层。

下面还是以leetcode中的题为例:

5d1255b9f5230df03367377bfd499e40.png

当看到这一题的时候,首先想到的就是一层一层的遍历,然后每遍历完一层以后,将这一层组成链表放入结果集中。

在二叉树的广度优先遍历中,需要借助到另外一种数据结构-队列

在遍历队列时,同时将当前节点的左右子树加入队列中,当遍历完一层以后,下一层也刚好全部加入到队列中,这样就实现了二叉树一层一层的遍历。

下面看看代码是如何实现的:

class Solution {
    public ListNode[] listOfDepth(TreeNode tree) {
        if (tree == null) {
            return null;
        }
        List ans = new ArrayList<>();
        Queue queue = new ArrayDeque<>();// 首先将根节点加入队列中
        queue.add(tree);while (!queue.isEmpty()) {// 最后加入集合中的需要是链表的头节点
            ListNode head = null;
            ListNode tail = null;// 遍历size长度,保证只遍历这一层数据int size = queue.size();for (int i = 0; i                 // 依次取出节点
                TreeNode treeNode = queue.poll();// 组成链表if (head == null) {
                    head = new ListNode(treeNode.val);
                    tail = head;
                } else {
                    tail.next = new ListNode(treeNode.val);
                    tail = tail.next;
                }// 将左右子节点加入队列中if (treeNode.left != null) {
                    queue.offer(treeNode.left);
                }if (treeNode.right != null) {
                    queue.offer(treeNode.right);
                }
            }// 将链表加入结果集中
            ans.add(head);
        }
        ListNode[] res = new ListNode[ans.size()];return ans.toArray(res);
    }
}

总结

最后总结一下,二叉树的遍历分为深度优先遍历和广度优先遍历

深度优先遍历又分为,前序遍历、中序遍历和后序遍历,实现方式可采用递归和迭代+栈

广度优先遍历的实现方式可采用迭代+队列


扫一扫,关注我
8f8f9d9423bb966447f8978d4b294319.png

往期推荐

Java面试系列-spring相关

Java面试系列-redis相关

Java面试系列-线程相关(一)

Java到底是引用传递还是值传递

手摸手教你搭建免费图床

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值