二叉树学习笔记

本文介绍了二叉树的各种遍历方法,包括递归和非递归实现的先序、中序、后序遍历,以及宽度优先遍历。同时,文章讨论了如何判断二叉树是否为搜索二叉树、完全二叉树、满二叉树和平衡二叉树,并提供了判断方法。此外,还涉及了寻找二叉树最低公共祖先(LCA)的问题,以及如何找到二叉树中节点的后继节点。最后提到了二叉树的序列化与反序列化,以及一个与折纸问题相关的满二叉树应用。
摘要由CSDN通过智能技术生成

二叉树

题目一

二叉树节点结构

public class Node<T> {
    T value;
    Node left;
    Node right;
}

注意:孩子节点仅有一个父节点,不能形成环。

用递归和非递归两种方式实现二叉树的先序、中序和后序遍历。

如何直观地打印一棵二叉树?

如何完成二叉树的宽度优先遍历(常见题目:求一棵二叉树的宽度)?

二叉树遍历的递归序

通过递归的方式遍历二叉树,把遍历过程展开得到的顺序为递归序。

public class TravesalRecur {
    public void travelRecur(Node head) {
        if (null == head) {
            return;
        }
        System.out.print(head.value);
        System.out.print(",");

        travelRecur(head.left);
        System.out.print(head.value);
        System.out.print(",");

        travelRecur(head.right);
        System.out.print(head.value);
        System.out.print(",");
    }
}

用递归方式实现二叉树的先序、中序和后序遍历

通过递归序实现先序、中序和后序遍历。

通过二叉树的递归序可以很容易地得出二叉树的先序、中序和后序遍历的实现方法。

用非递归方式实现二叉树的先序、中序和后序遍历

递归使用线程栈,大小有限制,递归层次太深,栈会溢出。

解决方案:

(1)限制递归深度;

(2)递归改写为非递归,利用栈结构,从内存分配空间。

非递归先序遍历

利用栈实现,压栈顺序为:头右左,出栈顺序为:头左右。

(1)头结点压栈;

(2)弹栈,打印节点;

(3)有右压栈,有左压栈,先右后左;

(4)循环执行(2),(3),直到栈为空。

非递归中序遍历

利用栈实现,压栈顺序为: 头左右 出栈顺序:左头右。

(1)从头结点开始;

(2)把每个节点的整棵树的左边界压栈;

(3)依次弹栈,打印;

(4)对每个弹出的节点,如果有右孩子,对右孩子重复执行(2),(3),直到栈为空。

非递归后序遍历

用1个栈的实现方式很难。

利用两个栈实现,1个栈,1个收集栈,压栈顺序为:头左右,出栈顺序为:头右左。

(1)头结点压栈;

(2)弹栈,压收集栈;

(3)有左压栈,有右压栈,先左后右;

(4)循环执行(2),(3),直到栈为空;

(5)依次弹出收集栈,打印。

如何完成二叉树的宽度优先遍历?

二叉树的深度优先遍历:和先序遍历一样。

利用队列完成,进队列的顺序:从上到下,从左到右。

(1)头结点进队列;

(2)出队列,打印;

(3)有左进队列,有右进队列;

(4)循环执行(2),(3),直到队列为空。

求一棵二叉树的宽度

实现一:利用Map保存每个节点所在的层级,对二叉树做宽度优先遍历计算出宽度。

实现二:利用几个变量,对二叉树做宽度优先遍历计算出宽度。

题目二

二叉树的相关概念及其实现方式

如何判断一棵二叉树是搜索二叉树?

如何判断一棵二叉树是完全二叉树?

如何判断一棵二叉树是满二叉树?

如何判断一棵二叉树是平衡二叉树?

二叉树题目套路(二叉树递归套路,树型DP)

搜索二叉树:整棵树和所有子树都满足,根节点比左子树的所有节点大,比右子树的所有节点小。中序遍历得到的序列按照升序排列。

完全二叉树:按照从上到下,从左到右的顺序填满节点的二叉树。只有最下边一层节点可以不填满,但是必须是按照从左到右的顺序填满,中间不能有空缺。

满二叉树:每一层的节点都是填满的,高度(h)和节点数(n)满足公式:n = 2^h - 1

平衡二叉树:整棵树和所有子树都满足,根节点的左子树高度与右子树高度相差不超过1。

二叉树题目套路:二叉树递归套路,解决树型DP问题,并不能解决所有二叉树的问题,需要具体问题具体分析。

(1)向左子树要信息;

(2)向右子树要信息;

(3)结合自身、左子树信息、右子树信息,根据约束条件计算出最终的结果。

注意:面试时二叉树相关的问题可以优先考虑。

如何判断一棵二叉树是搜索二叉树?

实现一:按照中序遍历,检查升序。

实现二:递归检查。

从根节点开始,对每个节点进行处理:

(1)向左子树获取搜索二叉树标志、最大值、最小值;

(2)向右子树获取搜索二叉树标志、最大值、最小值;

(3)然后检查条件:左子树、右子树都是搜索二叉树,并且根节点比左子树的最大值小、比右子树的最小值大,只要不满足就不是搜索二叉树。加工出本节点的搜索二叉树标志、最大值、最小值。

整棵树的每个节点会在递归检查过程中都会检查一遍,每个节点满足该检查条件则是搜索二叉树。

如何判断一棵二叉树是完全二叉树?

按照宽度优先遍历,检查:

(1)如果一个节点有右孩子,无左孩子,则不是完全二叉树;

(2)在(1)不违规的条件下,遇到第一个左右孩子不双全时,后续所有的节点必须是叶节点。

完全二叉树的所有子树并不都是完全二叉树,不能使用递归套路解决。

如何判断一棵二叉树是满二叉树?

实现一:获取高度h,获取节点个数n,如果满足公式:n = 2^h -1,则是满二叉树。

实现二:使用递归套路实现。从根节点开始,对每个节点进行处理:

(1)向左子树获取高度、节点个数;

(2)向右子树获取高度、节点个数;

(3)加工出本节点的高度、节点个数;

(4)通过以上递归处理过程获取整棵树的高度(h)、节点个数(n),如果满足公式:n = 2^h -1,则是满二叉树。

如何判断一棵二叉树是平衡二叉树?

使用递归套路实现。

从根节点开始,对每个节点进行处理:

(1)向左子树获取平衡二叉树标志、高度;

(2)向右子树获取平衡二叉树标志、高度;

(3)然后检查条件:左右子树的高度差不超过1。加工出本节点的平衡二叉树标志、高度。

题目三

给定两个二叉树的节点node1和node2,找到他们的最低公共祖先(LCA)。

实现一:(1)遍历二叉树利用HashMap把每个节点的父节点关系创建出来;

(2)利用整棵树的父节点关系把node1节点的父节点链创建出来;

(3)从node2节点还是往上(整棵树的跟节点)找,每获得一个父节点,检查该节点在不在node1的父节点链中,如果在该节点就是最低公共祖先。

实现二:类似树型DP,递归套路

所有可能的情况为:(1)node1是node2的LCA,或者node2是node1的LCA;

(2)node1和node2不互为LCA。

题目四

在二叉树的中序遍历的序列中,一个节点的下一个节点叫作它的后继节点。

在二叉树中找到一个节点的后继节点。有一棵新的二叉树的节点类型如下,每个节点parent指针指向父节点,头结点的parent为null。

public class Node { public int value; public Node left; public Node right; public Node parent;}

给定一个节点node,请找到它的后继节点。

实现一:按照中序遍历获得序列,然后找节点的后继节点。时间复杂度O(n),空间复杂度O(n)。

实现二:时间复杂度O(logn),空间复杂度O(1)。

(1)节点有右子树,后继为右子树的最左节点;

(2)节点无右子树,往上找父节点,找到的第一个是左孩子的父节点为后继节点;对于整棵树最右的节点,后继节点为null。

题目五

二叉树的序列化与反序列化

如何判断一棵二叉树是另一棵二叉树的子树

题目六

折纸问题

请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。此时折痕是凹下去的,即折痕突起的方向指向纸条的背面。如果从纸条的下边向上方连续对折2次,压出折痕后展开,此时有三条折痕,从上到下依次是下折痕、下折痕、上折痕。给定一个输入参数N,代表纸条都从下往上连续对折N次。请从上到下打印出所有折痕的方向。

例如:N=1时,打印:down。N=2时,打印:down down up

经分析可得出,折痕的分布对应一棵满二叉树,这棵二叉树的头结点是下折痕,每棵左子树的头结点是下折痕,每棵右子树的头结点是上折痕。从上到下折痕的顺序对应这棵满二叉树的中序遍历顺序。

实现一:空间复杂度O(2^N)。

(1)按照以上结论生成一棵高度N的二叉树;

(2)按照中序遍历打印。

实现方式二:空间复杂度O(N)。不生成完整的二叉树,使用递归套路实现。

参考资料

《bilibili左程云算法课堂》

源码地址

https://gitee.com/easyfun/algorithm-learning/tree/master/binary-tree

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值