【数据结构核心篇】树与哈希(Hash)的原理、特性及实战应用

一、树(Tree):分层有序的非线性结构

1.1 树的核心定义与基本术语

树是 n(n≥0) 个结点的有限集合,核心特征是分层、无环、仅有一个根节点

  • 空树:n=0 的特殊情况;
  • 非空树规则:
    1. 有且仅有一个 "根结点"(最顶层结点);
    2. 其余结点可分为 m 个互不相交的子集合(子树),每个子树仍是树。
关键术语
术语 定义
结点的度 结点拥有的子树个数
叶结点(终端结点) 度为 0 的结点(无子女)
分支结点(非终端结点) 度不为 0 的结点
树的度 树中所有结点的度的最大值
树的深度 / 高度 从根开始分层,根为第 1 层,叶子所在的最大层数为树的深度
树的存储方式
  • 顺序结构:基于数组存储(如完全二叉树的数组表示);
  • 链式结构:基于指针存储(如二叉树的链式结点),灵活性更高。

1.2 二叉树(Binary Tree):树的核心子集

二叉树是树中应用最广的结构,定义为:n 个结点的有限集合,要么为空,要么由根结点 + 左子树 + 右子树 组成(左右子树互不相交且有序)。

二叉树核心特点
  1. 每个结点最多有 2 棵子树(度≤2);
  2. 左 / 右子树有严格顺序,不可颠倒(即使只有 1 棵子树,也要区分左右);
  3. 空树、单结点树均属于二叉树。
特殊二叉树
类型 定义 核心特征
斜树 所有结点仅有左子树(左斜树)或仅有右子树(右斜树) 退化为单链表,查找效率 O (n)
满二叉树 所有分支结点都有左右子树,且叶子结点在同一层 深度为 k 时,结点总数 = 2ᵏ-1
完全二叉树 按层序编号后,每个结点的编号与同深度满二叉树的编号完全一致 叶子结点仅出现在最后两层,效率接近满二叉树
二叉树的核心特性(必背)
  1. i 层最多有 2^(i-1) 个结点(i≥1);
  2. 深度为 k 的二叉树,至多有 2ᵏ - 1 个结点(k≥1);
  3. 任意二叉树中,叶子结点数 n₀ = 度为 2 的结点数 n₂ + 1n₀ = n₂ + 1);
  4. n 个结点的完全二叉树,深度为 ⌊log₂n⌋ + 1(向下取整)。

1.3 二叉树的遍历方式

遍历是访问二叉树所有结点的核心操作,分为深度遍历广度(层序)遍历

1.3.1 广度遍历(层序遍历)
  • 规则:从上到下、从左到右按层访问结点;
  • 实现:借助队列(先进先出),根结点入队 → 出队访问 → 左右子结点入队 → 循环至队空;
  • 应用:按层打印、求树的宽度、找某一层的结点。
1.3.2 深度遍历(递归 / 栈实现)
遍历方式 规则 示例(根 A,左 B,右 C)
前序遍历 根 → 左 → 右 A → B → C
中序遍历 左 → 根 → 右 B → A → C
后序遍历 左 → 右 → 根 B → C → A

1.4 树的核心应用场景

  • 二叉搜索树(BST):有序存储,支持 O (logn) 查找 / 插入 / 删除;
  • 平衡二叉树(AVL / 红黑树):解决 BST 退化为链表的问题,用于 Map/Set 底层;
  • 堆(完全二叉树):优先队列、TopK 问题、排序(堆排序);
  • 多叉树:文件系统目录、XML/JSON 解析、数据库索引。

二、哈希(Hash):极速存取的映射技术

哈希(散列)是一种 "键 - 值" 映射技术,核心是通过哈希函数将数据的 "键(key)" 转换为存储位置,实现 O (1) 级别的存取效率。

2.1 哈希的核心定义

  • 存储位置 = f(key)
    • f:哈希函数(散列函数),负责将 key 转换为数组下标;
    • key:待存储 / 查询的数据;
    • 存储位置:数组中存储该数据的地址(下标)。
  • 核心载体:通常基于顺序表(数组) 实现(需支持随机访问)。

2.2 哈希函数的设计要点

一个优秀的哈希函数需满足两个核心条件:

  1. 计算简单:快速得到存储位置,避免额外性能开销;
  2. 地址分布均匀:尽量减少 "哈希冲突",提高空间利用率。
常见哈希函数设计方法
方法 原理 适用场景
直接定值法 f(key) = a*key + b(a、b 为常数) key 分布连续且范围小(如学号、员工编号)
平方取中法 将 key 平方后,取中间几位作为下标 key 分布随机(如字符串、不规则数字)
折叠法 将 key 拆分为等长段,叠加后取结果作为下标 key 位数多(如身份证号、手机号)
求余法 f(key) = key % size(size 为数组长度) 通用场景(最常用),建议 size 取质数

2.3 哈希冲突:不可避免的问题

冲突定义

f(key1) = f(key2)key1 ≠ key2:不同数据通过哈希函数计算出相同的存储位置。

冲突解决方法
方法 原理 优缺点
线性探测 冲突后依次尝试 +1、+2、+3... 直到找到空位置 实现简单,易产生 "堆积"(连续冲突)
二次探测 冲突后尝试 ±1²、±2²、±4²... 直到找到空位置 减少堆积,仍有局部冲突
随机探测 冲突后尝试 +rand()%size 随机位置 分布更均匀,需保证遍历所有位置
链地址法 数组每个位置存储一个链表,冲突数据挂在链表上 无堆积,效率稳定(HashMap 底层方案)

2.4 哈希的 ADT(抽象数据类型)定义

c

运行

复制代码
typedef int DATATYPE;
// 哈希表结构(数组实现)
typedef struct
{
    DATATYPE* head; // 哈希表数组指针
    int tlen;       // 哈希表总长度
} HS_TABLE;

// 核心操作函数
HS_TABLE* CreateHsTable(int len);        // 创建哈希表
int insertHsTable(HS_TABLE*hs,DATATYPE*data); // 插入数据
int SearchHsTable(HS_TABLE*hs,DATATYPE*data); // 查询数据
int DestroyHsTable(HS_TABLE*hs);         // 销毁哈希表

2.5 哈希的核心应用场景

  • 缓存系统(如 Redis):通过 key 极速查找 value;
  • 去重 / 计数(如统计字符出现次数);
  • 数据库索引:哈希索引(对比 B + 树索引);
  • 编程语言容器(如 Java HashMap、Python dict)。

三、树 vs 哈希:核心区别与选型建议

维度 树(以二叉搜索树为例) 哈希(链地址法)
时间复杂度 查找 / 插入 O (logn)(平衡树) 理想 O (1),冲突时 O (n)
有序性 天然有序(中序遍历可排序) 无序(需额外排序)
空间利用率 无浪费(链式存储) 需预留空间(避免冲突)
适用场景 有序查询、范围查找(如找 [10,20] 的数) 单点极速查询、键值映射
实现复杂度 较高(需处理平衡、遍历) 较低(核心是哈希函数 + 冲突处理)

选型建议

  • 有序 / 范围查询:选树(如红黑树、B + 树);
  • 极速单点查询:选哈希(如 HashMap);
  • 数据量小、简单场景:哈希更易实现;
  • 数据量大、需稳定性能:平衡树更可靠。

四、总结

  • :以二叉树为核心,通过分层有序存储实现 O (logn) 的查找效率,适合有序、层级化的场景,是解决 "有序遍历、范围查询" 的核心工具;
  • 哈希:通过 "键 - 位置" 映射实现 O (1) 极速存取,适合 "单点查询、键值映射" 场景,核心是哈希函数设计和冲突处理;
  • 两者互补:工程中常结合使用(如 Redis 的有序集合 = 哈希 + 跳表)。
相关推荐
ada7_7 小时前
LeetCode(python)——543.二叉树的直径
数据结构·python·算法·leetcode·职场和发展
橘颂TA7 小时前
【剑斩OFFER】算法的暴力美学——颜色分类
数据结构·c++·算法·动态规划
吴秋霖8 小时前
profileData纯算逆向分析
算法·设备指纹·反爬虫技术
sprintzer8 小时前
11.26-12.05力扣栈刷题
算法·leetcode·职场和发展
sin_hielo8 小时前
leetcode 3578
数据结构·算法·leetcode
ShiMetaPi8 小时前
SAM(通用图像分割基础模型)丨基于BM1684X模型部署指南
人工智能·算法·ai·开源·bm1684x·算力盒子
前端小白在前进8 小时前
力扣刷题:无重复字符的最长子串
算法·leetcode·职场和发展
小小的橙菜吖!8 小时前
联合体的学习
学习·算法
Xing_ke3099 小时前
3D点云分割与检测(后续更新)
算法·3d点云