前端会用到的数据结构--堆(HEAP)

堆是什么?

  1. 完全二叉树

    1. 除最后一层外,每层都填满
    2. 用数组存储非常高效,父子节点下标有规律
  2. 堆顶始终是最大或最小的数,便于快速取出。

应用场景

1️⃣ 堆排序(Heap Sort)

原理:构建一个最大堆,每次取堆顶元素(最大),放到数组末尾,重复堆化。

时间复杂度:O(n log k)

📌 应用:

  • 在一万条数据里,取最大的10个数
  • React 内部 reconciler 中有对 fiber list 的优先级调整过程(虽然更复杂)

2️⃣ React 的 scheduler 中的最小堆队列

React 17+ 中的 scheduler 模块用于调度更新任务,其核心是一个时间驱动的优先级队列

源码地址:

arduino 复制代码
js
复制编辑
const taskQueue = new HeapQueue();   // 按照 expirationTime 排序(时间优先)
const timerQueue = new HeapQueue();  // 按照 startTime 排序(定时任务)

这里使用的是 最小堆,以保证:

  • 取出最早过期或最早开始的任务是 O(1)
  • 插入/更新任务是 O(log n)

📌 相关概念:

  • expirationTime 决定任务的紧急程度(Lanes机制)
  • startTime 控制任务延迟开始(如 setTimeout

3️⃣ 前端动画调度器(如 requestIdleCallback polyfill)

浏览器的 requestIdleCallback 用于在浏览器空闲时间运行回调,类似的调度器内部也常用最小堆存储任务(按照预定的执行时间排序),例如:

yaml 复制代码
js
复制编辑
[
  { callback: fn1, time: 158000001 },
  { callback: fn2, time: 158000003 }
]

每一帧取出堆顶执行任务(即将过期的),其余任务继续等待。


4️⃣ 优先级任务队列 / 限流工具

你实现一个并发请求池(如 5 并发),但需要支持优先级调度,可用最大堆实现优先级队列:

javascript 复制代码
js
复制编辑
class Task {
  constructor(priority, callback) { ... }
}

堆顶是优先级最高的任务,先执行它。

📌 应用:

  • 文件上传任务队列(优先级)
  • 渲染任务(长列表懒加载)

5️⃣ 前端游戏 / 动画帧控制系统

在复杂的 WebGL、canvas 动画或游戏循环中,需要按执行时间调度任务帧 ------ 最小堆非常适合做这种"时间轴排序"。

例如:

scss 复制代码
js
复制编辑
scheduleAt(time, callback)

内部将任务按时间压入最小堆,当前帧时间到了就从堆顶拿任务执行。


为什么前端常用"最小堆"?

  • 因为前端调度大多数以**"时间驱动"或"优先级最小者先执行"**为主:

    • 比如:任务最早执行、超时最早发生、优先级最小者最紧急
  • 所以最小堆正好满足这个模型:堆顶是最小值,取用只要 O(1)


如何实现堆?

  • peek函数: 查看堆的顶点, 也就是优先级最高的tasktimer.
  • pop函数: 将堆的顶点提取出来, 并删除顶点之后, 需要调用siftDown函数向下调整堆.
  • push函数: 添加新节点, 添加之后, 需要调用siftUp函数向上调整堆.
  • siftDown函数: 向下调整堆结构, 保证数组是一个最小堆.
  • siftUp函数: 当插入节点之后, 需要向上调整堆结构, 保证数组是一个最小堆.

总结

面试官问:堆在前端有什么应用?
在前端开发中,堆主要应用在需要快速获取"最小/最大值"的任务调度场景中。例如:

  • React 中的 scheduler 模块使用最小堆管理任务队列,以 O(1) 获取优先级最高的任务
  • requestIdleCallback 的 polyfill 实现中,也会用最小堆安排任务执行时间
  • 自定义的并发任务队列(如上传、抓取)也可用最大堆做优先级控制
  • 当然,堆排序本身也可以用来实现稳定的 O(n log k) 排序

因为堆能在 log(n) 时间内插入任务,O(1) 获取最小值,所以非常适合调度类系统。

相关推荐
来杯三花豆奶2 分钟前
Vue 2.0 Mixins 详解:从原理到实践的深度解析
前端·javascript·vue.js
code_YuJun4 分钟前
脚手架开发工具——dotenv
前端
San30.10 分钟前
深度驱动:React Hooks 核心之 `useState` 与 `useEffect` 实战详解
前端·javascript·react.js
Mr_Swilder21 分钟前
vscode没有js提示:配置jsconfig配置
前端
skywalk816322 分钟前
使用Trae 自动编程:为小学生学汉语项目增加不同出版社教材的区分
服务器·前端·人工智能·trae
huohuopro31 分钟前
LangChain | LangGraph V1教程 #3 从路由器到ReAct架构
前端·react.js·langchain
柒.梧.1 小时前
HTML入门指南:30分钟掌握网页基础
前端·javascript·html
用户54277848515401 小时前
Promise :从基础原理到高级实践
前端
用户4099322502121 小时前
Vue3条件渲染中v-if系列指令如何合理使用与规避错误?
前端·ai编程·trae
Mr_Swilder1 小时前
2025-12-20 vue3中 eslint9+和prettier配置
前端