树与二叉树

树&二叉树(图解理解)



整体思维导图

在这里插入图片描述

一、树的基础概念

  1. 定义
    树(Tree) 是 n(n≥0)个节点的有限集合。n=0 时为空树;非空树满足:
    有且仅有一个根节点(Root),无父节点
    其余节点分为 m 个互不相交的有限集,每个集合本身是一棵树,称为子树
    在这里插入图片描述

  2. 核心术语
    节点(Node):树的基本单元,含数据域与指针域
    父节点 / 子节点:若节点 A 含子树 B,A 是 B 的父节点,B 是 A 的子节点
    叶子节点(Leaf):度为 0 的节点,无子节点
    度(Degree):节点的子节点个数;树的度是所有节点度的最大值
    深度(Depth):根节点深度为 1,子节点深度 = 父节点深度 + 1
    高度(Height):叶子节点高度为 1,父节点高度 = 子节点最大高度 + 1
    路径 / 路径长度:两节点间的边数为路径长度

  3. 树的特点
    非线性、层次化结构,无环、无交叉
    根节点唯一,非根节点仅有一个父节点
    子树个数不限,无序树(子树无固定顺序)

二、二叉树核心知识

  1. 定义与特点
    二叉树(Binary Tree) 是每个节点最多 2 个子节点的有序树,特点:
    节点度≤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   |
+-----------+-----------+-----------+

每个节点含数据、左指针、右指针,灵活存储任意二叉树

三、二叉树遍历(核心)

遍历:按规则访问所有节点,且仅访问一次,分前序、中序、后序、层序
在这里插入图片描述

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

在这里插入图片描述
2. 中序遍历(左→根→右,LNR)
规则:中序遍历左子树 → 访问根节点 → 中序遍历右子树
示例序列:D G B E A C F
在这里插入图片描述

  1. 后序遍历(左→右→根,LRN)
    规则:后序遍历左子树 → 后序遍历右子树 → 访问根节点
    示例序列:G D E B F C A
    在这里插入图片描述

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

在这里插入图片描述

  1. 递归代码(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 << " ";
    }
}

四、树与二叉树转换

  1. 树→二叉树
    规则:左孩子右兄弟
    节点的左孩子为原树最左子节点
    节点的右孩子为原树相邻右兄弟
    根节点无右兄弟,二叉树根无右子树
    在这里插入图片描述

  2. 二叉树→树
    规则:左孩子还原为子节点,右孩子还原为兄弟节点
    五、森林与二叉树转换

  3. 森林→二叉树
    每棵树转为二叉树
    第一棵树的根为总根
    后一棵树的根作为前一棵树根的右孩子
    在这里插入图片描述

  4. 二叉树→森林
    根的右子树拆分出第二棵树
    重复拆分右子树,得到多棵二叉树
    每棵二叉树还原为树
    六、关键应用场景
    文件系统:目录结构用树存储
    数据库索引:B + 树、红黑树优化查询
    表达式求值:二叉树表示表达式,后序遍历计算
    哈夫曼编码:最优二叉树实现数据压缩
    算法设计:二叉搜索、平衡树优化时间复杂度

应用场景

文件系统:目录结构用树存储
数据库索引:B + 树、红黑树优化查询
表达式求值:二叉树表示表达式,后序遍历计算
哈夫曼编码:最优二叉树实现数据压缩
算法设计:二叉搜索、平衡树优化时间复杂度

Buff叠加:文章中出现图片为引用各位大佬而来,若觉不适,私信可删

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值