二叉树基础及常见类型

简介: 二叉树是数据结构的核心,不仅是红黑树、堆、图等的基础,更体现了递归思维。掌握二叉树,等于掌握算法与数据结构的关键。本文详解满二叉树、完全二叉树、二叉搜索树及其实现方式,助你彻底理解其原理与应用,为后续算法学习打下坚实基础。

我认为二叉树是最重要的基本数据结构,没有之一。
如果你是初学者,现在这个阶段我很难给你彻底解释清楚得出这个结论的原因,你需要认真学习本站后面的内容才能逐渐理解。我暂且总结两个点:
1、二叉树本身是比较简单的基础数据结构,但是很多复杂的数据结构都是基于二叉树的,比如 红黑树(二叉搜索树)、多叉树、二叉堆、图、字典树、并查集、线段树 等等。你把二叉树玩明白了,这些数据结构都不是问题;如果你不把二叉树搞明白,这些高级数据结构你也很难驾驭。
2、二叉树不单纯是一种数据结构,更代表着递归的思维方式。一切递归算法,比如 回溯算法、BFS 算法、动态规划 本质上也是把具体问题抽象成树结构,你只要抽象出来了,这些问题最终都回归二叉树的问题。同样看一段算法代码,在别人眼里是一串文本,每个字都认识,但连起来就不认识了;而在你眼里的代码就是一棵树,想咋改就咋改,咋改都能改对,实在是太简单了。
后面的数据结构章节包含大量关于二叉树的讲解和习题,你按照本站的目录顺序学习,我会带你把二叉树彻底搞懂,到时候你就明白我为什么这么重视二叉树了。
几种常见的二叉树
二叉树的主要难点在于做算法题,它本身其实没啥难的,就是这样一种树形结构嘛:
上面就是一棵普通的二叉树,几个术语你要了解一下:
1、每个节点下方直接相连的节点称为子节点,上方直接相连的节点称为父节点。比方说节点 3 的父节点是 1,左子节点是 5,右子节点是 6;节点 5 的父节点是 3,左子节点是 7,没有右子节点。
2、我们称最上方那个没有父节点的节点 1 为根节点,称最下层没有子节点的节点 4、7、8 为叶子节点。
3、我们称从根节点到最下方叶子节点经过的节点个数为二叉树的最大深度/高度,上面这棵树的最大深度是 4,即从根节点 1 到叶子节点 7 或 8 的路径上的节点个数。
没啥别的可说的了,就是这么简单。有一些稍微特殊一些的二叉树,有他们自己的名字,你要了解一下,后面做题时见到这些专业术语,你就知道题目在说啥了。
满二叉树
直接看图比较直观,满二叉树就是每一层节点都是满的,整棵树像一个正三角形:
满二叉树有个优势,就是它的节点个数很好算。假设深度为 h,那么总节点数就是 2^h - 1,等比数列求和嘛,我们应该都学过的。
完全二叉树
完全二叉树指:二叉树每一层节点都紧凑靠左排列,且除了最后一层,其他每层都必须是满的:
不难发现,满二叉树其实是一种特殊的完全二叉树。完全二叉树的特点:由于它的节点紧凑排列,如果从左到右从上到下对它的每个节点编号,那么父子节点的索引存在明显的规律。
完全二叉树还有个比较难发觉的性质:完全二叉树的左右子树也是完全二叉树。或者更准确地说应该是:完全二叉树的左右子树中,至少有一棵是满二叉树

二叉搜索树
二叉搜索树(Binary Search Tree,简称 BST)是一种很常见的二叉树,它的定义是:对于树中的每个节点,其左子树的每个节点的值都要小于这个节点的值,右子树的每个节点的值都要大于这个节点的值。你可以简单记为「左小右大」。我把「子树的每个节点」加粗了,这是初学者常犯的错误,不要只看子节点,而要看整棵子树的所有节点。比方说,下面这棵树就是一棵 BST:
节点 7 的左子树所有节点的值都小于 7,右子树所有节点的值都大于 7;节点 4 的左子树所有节点的值都小于 4,右子树所有节点的值都大于 4,以此类推。下面这棵树就不是 BST:
如果你只注意每个节点的左右子节点,似乎看不出问题。你应该看整棵子树,注意看节点 7 的左子树中有个节点 8,比 7 大,这就不符合 BST 的定义了。
BST 是非常常用的数据结构。因为左小右大的特性,可以让我们在 BST 中快速找到某个节点,或者找到某个范围内的所有节点,这是 BST 的优势所在。
比方说,对于一棵普通的二叉树,其中的节点大小没有任何规律可言,那么你要找到某个值为 x 的节点,只能从根节点开始遍历整棵树。而对于 BST,你可以先对比根节点和 x 的大小关系,如果 x 比根节点大,那么根节点的整棵左子树就可以直接排除了,直接从右子树开始找,这样就可以快速定位到值为 x 的那个节点。
关于 BST,后面会专门章节详解,并且配有大量的习题,这里先讲些基础概念就够你用了。
二叉树的实现方式
最常见的二叉树就是类似链表那样的链式存储结构,每个二叉树节点有指向左右子节点的指针,这种方式比较简单直观。力扣/LeetCode 上给你输入的二叉树一般都是用这种方式构建的,二叉树节点类 TreeNode 一般长这样:
Java
运行代码
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { this.val = x; }
}

// 你可以这样构建一棵二叉树:
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.right.left = new TreeNode(5);
root.right.right = new TreeNode(6);

// 构建出来的二叉树是这样的:
// 1
// / \
// 2 3
// / / \
// 4 5 6
另外,在一般的算法题中,我们可能会把实际问题抽象成二叉树结构,但我们并不需要真的用 TreeNode 创建一棵二叉树出来,而是直接用类似 哈希表 的结构来表示二叉树/多叉树。比方说上面那棵二叉树
Java
运行代码
复制代码
1
2
3
4
5
1
/ \
2 3
/ / \
4 5 6
我可以用一个哈希表,其中的键是父节点 id,值是子节点 id 的列表(每个节点的 id 是唯一的),那么一个键值对就是一个多叉树节点了,这棵多叉树就可以表示成这样:
Java
运行代码
复制代码
1
2
3
4
5
6
7
8
// 1 -> [2, 3]
// 2 -> [4]
// 3 -> [5, 6]

HashMap> tree = new HashMap<>();
tree.put(1, Arrays.asList(2, 3));
tree.put(2, Collections.singletonList(4));
tree.put(3, Arrays.asList(5, 6));
这样就可以模拟和操作二叉树/多叉树结构,后文讲到图论的时候你就会知道,它有一个新的名字叫做 邻接表。

相关文章
|
4天前
|
Java API
用链表实现队列/栈
本文介绍如何用链表实现栈和队列,利用双链表头尾操作均为O(1)的特性,通过调用LinkedList API高效实现。栈可选头部或尾部作栈顶,队列同理,只需调整增删位置。文末引出数组实现队列的性能问题,启发优化思考。
|
4天前
|
存储 API 索引
队列/栈基本原理 ❗前置知识
本文介绍队列和栈两种“操作受限”的数据结构:队列遵循先进先出(FIFO),只能队尾入、队头出;栈遵循先进后出(FILO),仅在栈顶进行增删操作。二者底层多由数组或链表实现,核心API包括push、pop、peek和size,是后续复杂数据结构的基础。
|
4天前
|
Java 索引 容器
单/双链表代码实现
本文详解双链表与单链表的 MyLinkedList 实现,重点介绍三个关键优化:1)同时持有头尾节点引用,提升尾部操作效率;2)使用虚拟头尾节点简化边界处理;3)解析链表删除中的内存泄露误区,并强调指针置空的良好编程习惯。
|
3天前
|
存储 安全 开发工具
Git 的基础知识
在软件开发中,版本控制如Git至关重要,它支持代码历史追踪、团队协作、分支实验、错误回滚与代码审查。通过提供变更审计轨迹、备份恢复及功能隔离,提升开发效率与代码质量,助力团队高效协同,保障项目稳定演进。
|
4天前
|
存储 缓存 运维
一场FullGC故障排查
本文记录了一次JDOS容器CPU告警的排查过程,通过分析发现实际为JVM Full GC引发CPU占用升高。结合泰山与SGM监控,定位到堆内存中大对象导致老年代频繁占满。经JPofiler分析,确认问题源于将Excel数据以List&lt;Map&lt;String, String&gt;&gt;形式加载至内存,造成严重内存膨胀。最终提出优化方案:避免大对象驻留JVM或改用高效存储结构,降低GC压力。
|
3天前
|
存储 缓存 算法
学习数据结构和算法的框架思维
本文系统总结数据结构与算法本质:所有数据结构皆源于数组和链表,核心操作为遍历与访问;算法本质是穷举,关键在于无遗漏、无冗余。文章提炼出通用框架,帮助读者建立计算机思维,掌握高效解题方法,适合初学者建立全局观,也适合进阶者温故知新。
|
3天前
|
缓存 网络协议 算法
核心原理:能否画张图解释下 RPC 的通信流程?
RPC(远程过程调用)是一种实现分布式系统间通信的技术,它让调用远程服务像调用本地方法一样简单。本文深入浅出地讲解了RPC的定义、核心目标、通信流程及在微服务架构中的关键作用,帮助开发者理解其底层原理,掌握如何通过动态代理、序列化、协议设计等机制屏蔽网络复杂性,提升开发效率与系统可维护性。
|
3天前
|
消息中间件 Kubernetes 网络协议
别老想着怎么用好 RPC 框架,你得多花时间琢磨原理
2011年加入京东,亲历技术演进,现任技术架构部首席架构师。主导微服务、消息中间件等核心系统研发,深耕分布式架构。课程涵盖RPC基础、进阶与高级实战,带你掌握网络通信核心,构建高效可靠分布式系统。(238字)
|
3天前
|
算法 Java 索引
双指针技巧秒杀七道数组题目
本文介绍双指针技巧在数组和链表中的应用,重点解析快慢指针如何实现原地修改。通过LeetCode经典题如删除有序数组/链表重复项,展示如何用慢指针记录结果、快指针遍历数据,高效完成去重,时间复杂度O(N),避免频繁数据搬移。
|
3天前
|
算法
双指针技巧秒杀七道链表题目
本文总结单链表七大技巧:合并有序链表、链表分解、合并K个有序链表、找倒数第k个节点、找中点、判断环及起点、判断相交及交点,均基于双指针思想,涵盖LeetCode多道经典题目,助你系统掌握链表算法核心。