树&二叉树(图解理解)
整体思维导图

一、树的基础概念
-
定义
树(Tree) 是 n(n≥0)个节点的有限集合。n=0 时为空树;非空树满足:
有且仅有一个根节点(Root),无父节点
其余节点分为 m 个互不相交的有限集,每个集合本身是一棵树,称为子树

-
核心术语
节点(Node):树的基本单元,含数据域与指针域
父节点 / 子节点:若节点 A 含子树 B,A 是 B 的父节点,B 是 A 的子节点
叶子节点(Leaf):度为 0 的节点,无子节点
度(Degree):节点的子节点个数;树的度是所有节点度的最大值
深度(Depth):根节点深度为 1,子节点深度 = 父节点深度 + 1
高度(Height):叶子节点高度为 1,父节点高度 = 子节点最大高度 + 1
路径 / 路径长度:两节点间的边数为路径长度 -
树的特点
非线性、层次化结构,无环、无交叉
根节点唯一,非根节点仅有一个父节点
子树个数不限,无序树(子树无固定顺序)
二、二叉树核心知识
-
定义与特点
二叉树(Binary Tree) 是每个节点最多 2 个子节点的有序树,特点:
节点度≤2,分左孩子、右孩子,顺序不可颠倒
左、右子树均为二叉树,空树也是合法二叉树

-
特殊二叉树
(1)满二叉树
高度为 h,节点数 =2ʰ - 1,每层节点都 “满员”,无空缺

(2)完全二叉树
除最后一层外,其余层节点全满
最后一层节点靠左连续排列,右侧无空缺

(3)二叉排序树(BST)
左子树所有节点值 < 根节点值
右子树所有节点值 > 根节点值
左右子树均为二叉排序树,支持高效查找

(4)平衡二叉树(AVL)
任意节点的左右子树高度差≤1的二叉排序树,避免树退化
3. 重要性质
二叉树第 i 层最多有 2ⁱ⁻¹ 个节点(i≥1)
高度为 h 的二叉树最多 2ʰ - 1 个节点(满二叉树)
叶子节点数 n₀ = 度 2 节点数 n₂ + 1
含 n 个节点的完全二叉树高度 ⌊log₂n⌋ + 1
4. 存储结构
(1)顺序存储(数组)
适用于完全二叉树,节点下标对应位置
根节点:下标 1;左孩子:2i;右孩子:2i+1;父节点:⌊i/2⌋
非完全二叉树会浪费空间

(2)链式存储(二叉链表)
// 创建新节点
BiTree CreateNode(ElemType data) {
BiTree newNode = (BiTree)malloc(sizeof(BiTNode));
newNode->data = data;
newNode->lchild = NULL;
newNode->rchild = NULL;
return newNode;
}
// 插入左孩子
void InsertLeft(BiTree parent, ElemType data) {
if (parent == NULL) return;
parent->lchild = CreateNode(data);
}
BiTNode:
+-----------+-----------+-----------+
| data | lchild | rchild |
+-----------+-----------+-----------+
每个节点含数据、左指针、右指针,灵活存储任意二叉树
三、二叉树遍历(核心)
遍历:按规则访问所有节点,且仅访问一次,分前序、中序、后序、层序

- 前序遍历(根→左→右,NLR)
规则:访问根节点 → 前序遍历左子树 → 前序遍历右子树
示例序列:A B D G E C F

2. 中序遍历(左→根→右,LNR)
规则:中序遍历左子树 → 访问根节点 → 中序遍历右子树
示例序列:D G B E A C F

-
后序遍历(左→右→根,LRN)
规则:后序遍历左子树 → 后序遍历右子树 → 访问根节点
示例序列:G D E B F C A

-
层序遍历(按层从上到下、从左到右)
实现:用队列,根节点入队 → 出队访问 → 左右孩子入队 → 重复至队空
示例序列:A B C D E F G

- 递归代码(C 语言)
// 前序遍历
void PreOrder(BiTree T) {
if(T) {
// 访问根
printf("%c ", T->data);
// 遍历左子树
PreOrder(T->lchild);
// 遍历右子树
PreOrder(T->rchild);
}
}
// 中序遍历
void InOrder(BiTree T) {
if(T) {
InOrder(T->lchild);
printf("%c ", T->data);
InOrder(T->rchild);
}
}
// 后序遍历
void PostOrder(BiTree T) {
if(T) {
PostOrder(T->lchild);
PostOrder(T->rchild);
printf("%c ", T->data);
}
}
C++代码
#include <iostream>
struct BiTreeNode {
char data;
BiTreeNode* lchild;
BiTreeNode* rchild;
};
void PreOrder(BiTreeNode* T) {
if(T) {
std::cout << T->data << " ";
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}
void InOrder(BiTreeNode* T) {
if(T) {
InOrder(T->lchild);
std::cout << T->data << " ";
InOrder(T->rchild);
}
}
void PostOrder(BiTreeNode* T) {
if(T) {
PostOrder(T->lchild);
PostOrder(T->rchild);
std::cout << T->data << " ";
}
}
四、树与二叉树转换
-
树→二叉树
规则:左孩子右兄弟
节点的左孩子为原树最左子节点
节点的右孩子为原树相邻右兄弟
根节点无右兄弟,二叉树根无右子树

-
二叉树→树
规则:左孩子还原为子节点,右孩子还原为兄弟节点
五、森林与二叉树转换 -
森林→二叉树
每棵树转为二叉树
第一棵树的根为总根
后一棵树的根作为前一棵树根的右孩子

-
二叉树→森林
根的右子树拆分出第二棵树
重复拆分右子树,得到多棵二叉树
每棵二叉树还原为树
六、关键应用场景
文件系统:目录结构用树存储
数据库索引:B + 树、红黑树优化查询
表达式求值:二叉树表示表达式,后序遍历计算
哈夫曼编码:最优二叉树实现数据压缩
算法设计:二叉搜索、平衡树优化时间复杂度
应用场景
文件系统:目录结构用树存储
数据库索引:B + 树、红黑树优化查询
表达式求值:二叉树表示表达式,后序遍历计算
哈夫曼编码:最优二叉树实现数据压缩
算法设计:二叉搜索、平衡树优化时间复杂度
Buff叠加:文章中出现图片为引用各位大佬而来,若觉不适,私信可删

5712

被折叠的 条评论
为什么被折叠?



