TypeScript 队列实战:从零实现简单、循环、双端、优先队列,附完整测试代码
TypeScript 队列实战从零实现简单、循环、双端、优先队列附完整测试代码引言队列Queue是计算机科学中最基础也最实用的数据结构之一遵循FIFO先进先出原则。在实际开发中从任务调度到消息中间件从广度优先搜索到滑动窗口算法队列无处不在。本文将通过 TypeScript 从零实现四种经典队列并附带完整的单元测试代码帮助你深入理解队列的底层原理。## 1. 简单队列Simple Queue简单队列是最基础的实现支持enqueue入队和dequeue出队操作。我们使用数组作为底层存储。typescript// 简单队列接口interface IQueueT { enqueue(element: T): void; dequeue(): T | undefined; peek(): T | undefined; isEmpty(): boolean; size(): number;}// 简单队列实现class SimpleQueueT implements IQueueT { private items: T[] []; // 入队将元素添加到队列尾部 enqueue(element: T): void { this.items.push(element); } // 出队移除并返回队列头部元素 dequeue(): T | undefined { if (this.isEmpty()) { return undefined; } return this.items.shift(); } // 查看队列头部元素不移除 peek(): T | undefined { if (this.isEmpty()) { return undefined; } return this.items[0]; } // 判断队列是否为空 isEmpty(): boolean { return this.items.length 0; } // 获取队列大小 size(): number { return this.items.length; }}// 测试代码const simpleQueue new SimpleQueuenumber();simpleQueue.enqueue(10);simpleQueue.enqueue(20);simpleQueue.enqueue(30);console.log(简单队列测试:);console.log(出队:, simpleQueue.dequeue()); // 10console.log(队列大小:, simpleQueue.size()); // 2console.log(队列是否为空:, simpleQueue.isEmpty()); // false性能分析简单队列的dequeue操作使用shift()时间复杂度为 O(n)因为数组需要移动后续元素。这在数据量较大时效率较低。## 2. 循环队列Circular Queue循环队列通过复用数组空间解决简单队列的 O(n) 问题使用头尾指针实现 O(1) 的入队和出队。typescript// 循环队列实现class CircularQueueT { private items: (T | undefined)[]; // 底层数组允许 undefined 占位 private head: number 0; // 头指针 private tail: number 0; // 尾指针 private count: number 0; // 当前元素个数 private capacity: number; // 队列容量 constructor(capacity: number) { this.capacity capacity; this.items new Array(capacity).fill(undefined); } // 入队在尾部添加元素 enqueue(element: T): boolean { if (this.isFull()) { console.warn(队列已满无法入队); return false; } this.items[this.tail] element; // 在 tail 位置放入元素 this.tail (this.tail 1) % this.capacity; // 循环移动 tail this.count; return true; } // 出队移除并返回头部元素 dequeue(): T | undefined { if (this.isEmpty()) { return undefined; } const element this.items[this.head]; // 获取头部元素 this.items[this.head] undefined; // 清理空间 this.head (this.head 1) % this.capacity; // 循环移动 head this.count--; return element; } // 判断队列是否为空 isEmpty(): boolean { return this.count 0; } // 判断队列是否已满 isFull(): boolean { return this.count this.capacity; } // 查看头部元素 peek(): T | undefined { return this.items[this.head]; } // 获取当前元素个数 size(): number { return this.count; }}// 测试循环队列const circularQueue new CircularQueuenumber(3);circularQueue.enqueue(1);circularQueue.enqueue(2);circularQueue.enqueue(3);console.log(\n循环队列测试:);console.log(入队 4队列已满:, circularQueue.enqueue(4)); // falseconsole.log(出队:, circularQueue.dequeue()); // 1console.log(再次入队 4:, circularQueue.enqueue(4)); // trueconsole.log(队列状态:);while (!circularQueue.isEmpty()) { console.log(出队:, circularQueue.dequeue()); // 2, 3, 4}核心优势所有操作均为 O(1)适合固定容量的场景如操作系统中的任务队列。## 3. 双端队列Deque双端队列允许在两端进行插入和删除结合了栈和队列的特性。typescript// 双端队列实现class DequeT { private items: T[] []; private front: number 0; // 前端指针 private back: number 0; // 后端指针 // 从前端添加元素 addFront(element: T): void { // 如果队列为空直接添加到后端 if (this.isEmpty()) { this.addBack(element); return; } // 否则在 front 之前插入需要扩展数组 this.front--; // 如果 front 变为负数需要调整数组 if (this.front 0) { this.items.unshift(element); // 在数组头部插入 this.front 0; this.back; } else { this.items[this.front] element; } } // 从后端添加元素 addBack(element: T): void { this.items[this.back] element; this.back; } // 从前端移除元素 removeFront(): T | undefined { if (this.isEmpty()) return undefined; const element this.items[this.front]; this.items[this.front] undefined as any; this.front; if (this.front this.back) { this.front 0; this.back 0; } return element; } // 从后端移除元素 removeBack(): T | undefined { if (this.isEmpty()) return undefined; this.back--; const element this.items[this.back]; this.items[this.back] undefined as any; if (this.front this.back) { this.front 0; this.back 0; } return element; } // 查看前端元素 peekFront(): T | undefined { return this.items[this.front]; } // 查看后端元素 peekBack(): T | undefined { return this.items[this.back - 1]; } isEmpty(): boolean { return this.front this.back; } size(): number { return this.back - this.front; }}// 测试双端队列const deque new Dequenumber();deque.addBack(1);deque.addBack(2);deque.addFront(0);console.log(\n双端队列测试:);console.log(前端元素:, deque.peekFront()); // 0console.log(后端元素:, deque.peekBack()); // 2console.log(移除前端:, deque.removeFront()); // 0console.log(移除后端:, deque.removeBack()); // 2console.log(队列大小:, deque.size()); // 1应用场景双端队列常用于实现撤销操作、滑动窗口最大值问题等。## 4. 优先队列Priority Queue优先队列中的每个元素都有优先级优先级高的元素优先出队。我们使用最小堆作为底层实现。typescript// 优先队列节点interface PriorityNodeT { element: T; priority: number;}// 优先队列实现使用最小堆class PriorityQueueT { private heap: PriorityNodeT[] []; // 入队插入元素并保持堆结构 enqueue(element: T, priority: number): void { const node: PriorityNodeT { element, priority }; this.heap.push(node); this.bubbleUp(this.heap.length - 1); } // 出队移除并返回优先级最高的元素 dequeue(): T | undefined { if (this.isEmpty()) return undefined; const min this.heap[0]; const last this.heap.pop()!; if (!this.isEmpty()) { this.heap[0] last; this.sinkDown(0); } return min.element; } // 上浮操作插入时使用 private bubbleUp(index: number): void { while (index 0) { const parentIndex Math.floor((index - 1) / 2); if (this.heap[index].priority this.heap[parentIndex].priority) { break; } [this.heap[index], this.heap[parentIndex]] [this.heap[parentIndex], this.heap[index]]; index parentIndex; } } // 下沉操作删除时使用 private sinkDown(index: number): void { const length this.heap.length; while (true) { let smallest index; const leftChild 2 * index 1; const rightChild 2 * index 2; if (leftChild length this.heap[leftChild].priority this.heap[smallest].priority) { smallest leftChild; } if (rightChild length this.heap[rightChild].priority this.heap[smallest].priority) { smallest rightChild; } if (smallest index) break; [this.heap[index], this.heap[smallest]] [this.heap[smallest], this.heap[index]]; index smallest; } } isEmpty(): boolean { return this.heap.length 0; } size(): number { return this.heap.length; }}// 测试优先队列const priorityQueue new PriorityQueuestring();priorityQueue.enqueue(紧急任务, 1);priorityQueue.enqueue(普通任务, 3);priorityQueue.enqueue(次要任务, 5);priorityQueue.enqueue(重要任务, 2);console.log(\n优先队列测试:);console.log(出队顺序:);while (!priorityQueue.isEmpty()) { console.log(priorityQueue.dequeue()); // 紧急任务, 重要任务, 普通任务, 次要任务}核心思想最小堆保证根节点始终是优先级最高的元素所有操作时间复杂度为 O(log n)。## 5. 完整测试套件为了验证所有队列的正确性我们编写一个完整的测试函数typescript// 统一测试函数function testQueueT( queue: any, operations: Array{ op: string; args?: any[] }, expected: any[]): void { let result: any[] []; operations.forEach(({ op, args }) { switch (op) { case enqueue: queue.enqueue(...(args || [])); break; case dequeue: result.push(queue.dequeue()); break; case peek: result.push(queue.peek()); break; case size: result.push(queue.size()); break; case isEmpty: result.push(queue.isEmpty()); break; default: break; } }); console.log(测试结果:, JSON.stringify(result)); console.log(预期结果:, JSON.stringify(expected)); const passed JSON.stringify(result) JSON.stringify(expected); console.log(passed ? ✅ 测试通过 : ❌ 测试失败);}// 运行测试console.log( 队列通用测试 );const testQueueInstance new SimpleQueuenumber();testQueue(testQueueInstance, [ { op: enqueue, args: [1] }, { op: enqueue, args: [2] }, { op: dequeue }, { op: enqueue, args: [3] }, { op: dequeue }, { op: dequeue }, { op: isEmpty } ], [1, 2, 3, true]);## 总结通过本文的实战我们使用 TypeScript 实现了四种经典队列1.简单队列基于数组实现简单但出队效率低O(n)2.循环队列通过指针复用空间实现 O(1) 操作适合固定容量场景3.双端队列支持两端操作灵活性强4.优先队列基于最小堆保障高优先级元素优先出队在实际开发中选择哪种队列取决于具体需求- 任务调度系统优先队列- 消息中间件循环队列固定缓冲区- 编辑器撤销功能双端队列- 简单流程控制简单队列掌握这些队列的实现原理不仅能提升你的编码能力还能帮助你更好地理解操作系统、数据库等底层系统的工作原理。希望本文的代码示例能成为你日常开发中的实用参考。

相关新闻

3分钟快速上手PyTorch Geometric:构建你的第一个图神经网络

3分钟快速上手PyTorch Geometric:构建你的第一个图神经网络

3分钟快速上手PyTorch Geometric:构建你的第一个图神经网络 【免费下载链接】pytorch_geometric Graph Neural Network Library for PyTorch 项目地址: https://gitcode.com/GitHub_Trending/py/pytorch_geometric 你是否曾被复杂的图神经网络(GN…

2026/9/21 23:47:20 阅读更多 →
如何在React表单中集成Turnstile:提升安全性的完整指南

如何在React表单中集成Turnstile:提升安全性的完整指南

如何在React表单中集成Turnstile:提升安全性的完整指南 【免费下载链接】react-turnstile Cloudflare Turnstile integration for React. 项目地址: https://gitcode.com/gh_mirrors/re/react-turnstile React Turnstile是Cloudflare Turnstile在React应用中…

2026/9/19 4:15:06 阅读更多 →
Redis-Search终极指南:高性能实时前缀搜索如何革新Rails应用体验

Redis-Search终极指南:高性能实时前缀搜索如何革新Rails应用体验

Redis-Search终极指南:高性能实时前缀搜索如何革新Rails应用体验 【免费下载链接】redis-search Deprecated! High performance real-time prefix search, indexes store in Redis for Rails application 项目地址: https://gitcode.com/gh_mirrors/re/redis-sear…

2026/9/21 17:30:31 阅读更多 →

最新新闻

3个细节教你搞定优秀事迹怎么写新手避坑指南

3个细节教你搞定优秀事迹怎么写新手避坑指南

3个细节教你搞定优秀事迹怎么写新手避坑指南 面试现场,面试官盯着你的简历问:“你那个‘优秀事迹’具体怎么落地的?底层逻辑是什么?”你脑子一抽,只记得写了“工作认真、业绩突出”,却答不上来具体的量化指标、技术难点或业务闭环原理。别慌,这种“背…

2026/9/22 19:42:41 阅读更多 →
等待图片面试必问

等待图片面试必问

拒绝死等:手写实现异步加载,搞定图片等待难题 配置环境就卡半天,这是很多刚入行嵌入式开发的兄弟最真实的写照。 你盯着屏幕,代码逻辑明明没问题,为什么图片就是不显示?或者页面加载时,图片区域白花花一片,用户以为系统卡死了。这时候,很多人只会用…

2026/9/22 19:42:41 阅读更多 →
家庭记账软件哪个好?Python实战从入门到精通

家庭记账软件哪个好?Python实战从入门到精通

家庭记账软件哪个好?Python实战从入门到精通 刚复制来的代码在本地跑不通,报错信息满屏飘,这种崩溃感我懂。很多新手卡在环境配置和逻辑报错上,以为是自己笨,其实多半是忽略了底层细节。想要真正掌握 家庭记账软件哪个好…

2026/9/22 19:42:41 阅读更多 →
5个实战技巧搞定ae官网下载卡顿与性能优化

5个实战技巧搞定ae官网下载卡顿与性能优化

5个实战技巧搞定ae官网下载卡顿与性能优化 是不是看了一堆教程,结果打开项目还是卡成PPT?很多开发者在尝试通过ae官网下载素材或插件时,常遇到资源加载缓慢、内存溢出甚至崩溃的问题。这不仅仅是网络带宽的锅,更深层的原因在于本地渲染管线与浏览…

2026/9/22 19:41:40 阅读更多 →
主管级性能优化实战:3个面试必问底层原理,别再只会背八股

主管级性能优化实战:3个面试必问底层原理,别再只会背八股

主管级性能优化实战:3个面试必问底层原理,别再只会背八股 面试被问原理答不上来,那种尴尬真的没脸见人。很多兄弟平时刷题挺溜,代码也能跑,但面试官一追问“为什么这么写”或者“底层是怎么实现的”,瞬间卡壳。这背后暴露的不是知识储备不足,而是对…

2026/9/22 19:41:40 阅读更多 →
避坑指南:智机网学时认定图解原理,3步解决项目卡壳难题

避坑指南:智机网学时认定图解原理,3步解决项目卡壳难题

避坑指南:智机网学时认定图解原理,3步解决项目卡壳难题 做公路工程这行,最让人头大的是什么?不是图纸画错,也不是现场协调难,而是明明刷完了课,系统里却显示学时不足。很多人盯着“智机网”后台,心里直打鼓:这到底卡在哪一步?为什么别人一键通过,…

2026/9/22 19:41:40 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/22 4:32:41 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/22 4:38:57 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/22 8:51:04 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/22 2:43:42 阅读更多 →