二叉树入门:概念、存储与 C 语言实现
一、先把树的几个概念捋顺
树是典型的非线性结构。它由有限个结点组成,带着明显的层次关系;其中有一个结点叫根结点,除此之外,每个结点下面还可以挂若干子树。
几个常见术语不用死记,理解关系就够了:
- 结点的度:一个结点下面有多少棵子树。
- 叶结点:度为 0 的结点,也就是不再往下分支的点。
- 双亲结点:某个结点的上一级结点。
- 子结点:挂在某个结点下面的结点。
- 树的高度:整棵树里层数最多的那一层。
二、二叉树到底特殊在哪
二叉树是树里最常见的一类。它的限制很直接:每个结点最多只有两个孩子,通常叫左子树和右子树。也正因为有左右之分,它是有序树,左右不能随便换。
1. 两种常见的特殊二叉树
- 满二叉树:每一层的结点数都达到这一层能容纳的最大值。深度为 K 时,结点总数是
2^K - 1。 - 完全二叉树:除了最后一层,前面的层都排满了;最后一层也要尽量靠左连续排列。满二叉树可以看成完全二叉树的一个特例。
2. 为什么完全二叉树适合顺序存储
完全二叉树的编号连续,用数组存最省事。逻辑上它还是一棵树,物理上却是一段连续内存。这个办法对完全二叉树很舒服,但拿去存普通二叉树就容易浪费空间,空位会很多。
3. 常用性质
- 若根结点层数记为 1,那么第
i层最多有2^(i-1)个结点。 - 若根结点层数记为 1,深度为
h的二叉树最多有2^h - 1个结点。 - 对任意二叉树,设度为 0 的结点个数为
n₀,度为 2 的结点个数为n₂,则有n₀ = n₂ + 1。 - 具有
n个结点的满二叉树深度满足h = log₂(n + 1)。 - 对于按从上到下、从左到右顺序编号的完全二叉树,数组下标从 0 开始时:父结点下标为
i,左孩子是2 * i + 1,右孩子是2 * i + 2;反过来,孩子下标为i时,父结点下标是(i - 1) / 2。
三、链式存储更适合普通二叉树
普通二叉树通常不适合数组存储,尤其是结构不够规整的时候,数组里的空洞太多。更常见的做法是链式存储:每个结点保存数据,再带两个指针,分别指向左孩子和右孩子。
1. 结点定义
这里把数据类型先定义成 char,后面如果要换成 int 或别的类型,也比较方便。
// BTNode.h
#pragma once
#include "Queue.h"
typedef char BTDataType;
typedef struct {
BTDataType data;
} BTNode;

