前言
二叉树是树结构里最重要的子集,也是堆、平衡二叉树、红黑树、B + 树的底层基础。在写代码、刷算法、面试中高频出现。本文避开真题,专注讲概念、特殊二叉树、核心性质、存储方式、堆(二叉树顺序存储)。
2.1 二叉树的定义
二叉树:每个结点最多只有两个子结点,子结点分左孩子、右孩子,顺序不能颠倒。
结点组成三部分:
- 数据域:保存结点数据
- 左指针:指向左孩子
- 右指针:指向右孩子
重点区别普通树:普通树子节点不分左右;二叉树严格区分左孩子、右孩子。 空二叉树:结点数量为 0。
二叉树的几个结构

2.2 几个特殊的二叉树
2.2.1 满二叉树
每一层结点数都达到该层最大数量。 高度为 h. 特点:所有叶子结点都在最底层,没有结点只有单边孩子。

2.2.2 完全二叉树
满二叉树去掉最底层右侧若干结点得到。
- 除最后一层以外,其余每一层全部结点都是满的
- 最后一层结点靠左紧密排列,不能出现右边有结点、左边空缺
核心价值:完全二叉树可以直接用数组顺序存储,不需要指针,堆就是基于完全二叉树实现。

没有左子树就没有右子树,上层未铺满,不能有下层
2.2.3 搜索二叉树(BST,二叉搜索树)
二叉树满足:
- 左子树上所有结点的值 < 当前结点值
- 右子树上所有结点的值 > 当前结点值 左右子树也必须满足二叉搜索树规则。
作用:适合做查找,中序遍历 BST 可以得到升序序列。
2.3 二叉树四大核心性质
i 从 1 开始计数;n 代表结点总数;h 代表树高度

性质 4 :n 个结点完全二叉树,高度 
完全二叉树下标从 0 开始的数组下标关系:
- 父下标:
parent - 左孩子下标:
2*parent + 1 - 右孩子下标:
2*parent + 2 - 孩子下标为 child,父节点下标:
(child‑1)/2向下取整
这个下标映射,就是堆实现的底层原理。
2.4 二叉树两种存储结构
2.4.1 顺序存储结构
使用数组存放结点,只适合完全二叉树 / 堆。 普通二叉树不适合顺序存储:会大量空位,数组空间浪费严重。

优点:不用指针,下标直接找父子,缓存友好。 缺点:非完全二叉树空间利用率极低。
2.4.2 链式存储结构
最常用,二叉链表。
typedef struct BTNode
{
int data;
struct BTNode* lchild;
struct BTNode* rchild;
}BTNode;
每个结点存数据、左孩子指针、右孩子指针。 大部分二叉树算法(遍历、求高度、找结点)都基于链式存储。

2.5 二叉树顺序存储 ------ 堆
堆本质就是完全二叉树的数组实现。分为大根堆、小根堆。
2.5.1 堆的定义
- 小根堆:父结点 ≤ 左右孩子结点,堆顶(数组下标 0)是整堆最小值。
- 大根堆:父结点 ≥ 左右孩子结点,堆顶是整堆最大值。
注意:堆只保证父子大小关系,不保证整棵树有序,左右孩子之间没有大小约束。
2.5.2 堆两大核心算法:向上调整 AdjustUp、向下调整 AdjustDown
- AdjustUp 向上调整(插入用) 新元素放在数组末尾,不断和父节点比较;如果不满足堆规则,交换,一直向上,直到符合堆条件。对应堆的插入操作。
- AdjustDown 向下调整(删除、建堆用) 父节点和左右孩子比较,选出符合堆规则的孩子,交换;向下递归,直到满足堆条件。


2.5.3 堆的插入
- 数据放到数组末尾
- size++
- 调用 AdjustUp 向上调整

2.5.4 堆的删除(删除堆顶)
- 堆顶和数组最后一个元素交换
- size--(逻辑删除末尾)
- 对堆顶位置调用 AdjustDown 向下调整

不会直接删除数组头部,直接删头部数组挪动代价很大,交换末尾元素是堆删除的精髓。
2.5.5 堆的应用
- 堆排序:利用大根堆小根堆做排序
- TopK 问题:海量数据找最大 / 最小前 K 个元素
- 优先级队列,操作系统任务调度优先队列底层就是堆