堆结构(Heap)的基本实现【数据结构与算法—TypeScript 实现】
笔记整理自 coderwhy 『TypeScript 高阶数据结构与算法』课程
概念
本质:一种特殊的树结构,由 完全二叉树 实现
- 多数情况为二叉堆
- 二叉堆:最大堆、最小堆
- 最大堆:堆上的每个节点都的 大于等于(>=) 其子节点
- 最小堆:堆上的每个节点都 小于等于(<=) 其子节点
特性
- 高效解决获取最大值和最小值问题(Top K 问题)
- 底层使用 数组 实现
索引问题:
i = 0为根节点- 父节点索引:
Math.floor((i - 1) / 2) - 左子节点索引:
2i + 1 - 右子节点索引:
2i + 2 - 最后一个非叶子节点索引:
Math.floor((this.length - 1) / 2)
设计
属性:
- data:存储堆中的元素,通常使用数组实现
- length:堆中元素的数量
方法:
- insert(value):插入元素
- extract:提取 最大值 / 最小值
- peek:返回 最大值 / 最小值
- size:获取堆数量
- isEmpty:判断是否为空
- buildHeap(list):通过列表构造堆
- swap(i, j):两数交换
具体实现代码
class Heap<T> {
// 存储堆元素
private data: T[] = [];
// 堆元素数量
private length: number = 0;
constructor(list: T[] = []) {
this.buildHeap(list);
}
// 两数交换
private swap(i: number, j: number) {
const temp = this.data[i];
this.data[i] = this.data[j];
this.data[j] = temp;
}
// 获取堆数量
get size(): number {
return this.length;
}
// 返回最大值/最小值
peek(): T | undefined {
return this.data[0];
}
// 判断是否为空
isEmpty(): boolean {
return this.length === 0;
}
// 插入元素
insert(value: T) {
// 直接把新元素放入数组尾部
this.data.push(value);
this.length++;
this.heapify_up();
}
// 上滤操作
heapify_up() {
// 获取插入元素索引
let currentIndex = this.length - 1;
// 只要 currentIndex > 0 就一直循环
while (currentIndex > 0) {
// 获取父节点索引
let parentIndex = Math.floor((currentIndex - 1) / 2);
// 子节点小于父子点,不需交换数据
if (this.data[currentIndex] <= this.data[parentIndex]) {
break;
}
// 交换父子节点数据
this.swap(currentIndex, parentIndex);
// 更新当前节点索引
currentIndex = parentIndex;
}
}
// 提取
extract(): T | undefined {
// 1. 边界情况处理
if (this.length === 0) return undefined;
if (this.length === 1) {
this.length--;
return this.data.pop();
}
// 2. 提取并需要返回的最大值
const topValue = this.data[0];
this.data[0] = this.data.pop()!;
this.length--;
// 3. 维护最大堆的特性:下滤操作
this.heapify_down(0);
return topValue;
}
// 下滤操作
heapify_down(start: number) {
let index = start;
while (2 * index + 1 < this.length) {
let leftChildIndex = 2 * index + 1;
let rightChildIndex = 2 * index + 2;
let largerIndex = leftChildIndex;
if (rightChildIndex < this.length && this.data[rightChildIndex] > this.data[leftChildIndex]) {
largerIndex = rightChildIndex;
}
// 子节点大于当前节点,则交换位置
if (this.data[largerIndex] > this.data[index]) {
this.swap(largerIndex, index);
index = largerIndex;
} else {
break;
}
}
}
// 原地建堆
buildHeap(list: T[]) {
this.data = list;
this.length = list.length;
// 获取最后一个非叶子节点的索引
const start = Math.floor((this.length - 1) / 2);
for (let i = start; i >= 0; i--) {
this.heapify_down(i);
}
}
}
const heap = new Heap<number>([9, 11, 20, 56, 23, 45]);
// heap.insert(1);
// heap.insert(4);
// heap.insert(15);
// console.log(heap.extract());
console.log(heap);
堆结构(Heap)的基本实现【数据结构与算法—TypeScript 实现】的更多相关文章
- python数据结构与算法
最近忙着准备各种笔试的东西,主要看什么数据结构啊,算法啦,balahbalah啊,以前一直就没看过这些,就挑了本简单的<啊哈算法>入门,不过里面的数据结构和算法都是用C语言写的,而自己对p ...
- [数据结构]——堆(Heap)、堆排序和TopK
堆(heap),是一种特殊的数据结构.之所以特殊,因为堆的形象化是一个棵完全二叉树,并且满足任意节点始终不大于(或者不小于)左右子节点(有别于二叉搜索树Binary Search Tree).其中,前 ...
- 数据结构 之 二叉堆(Heap)
注:本节主要讨论最大堆(最小堆同理). 一.堆的概念 堆,又称二叉堆.同二叉查找树一样,堆也有两个性质,即结构性和堆序性. 1.结构性质: 堆是一棵被完全填满的二叉树,有可能的 ...
- 数据结构——堆(Heap)大根堆、小根堆
目录 Heap是一种数据结构具有以下的特点: 1)完全二叉树: 2)heap中存储的值是偏序: Min-heap: 父节点的值小于或等于子节点的值: Max-heap: 父节点的值大于或等于子节点的值 ...
- js数据结构与算法存储结构
数据结构(程序设计=数据结构+算法) 数据结构就是关系,没错,就是数据元素相互之间存在的一种或多种特定关系的集合. 传统上,我们把数据结构分为逻辑结构和物理结构. 逻辑结构:是指数据对象中数据元素之间 ...
- Java数据结构和算法 - 堆
堆的介绍 Q: 什么是堆? A: 这里的“堆”是指一种特殊的二叉树,不要和Java.C/C++等编程语言里的“堆”混淆,后者指的是程序员用new能得到的计算机内存的可用部分 A: 堆是有如下特点的二叉 ...
- 【数据结构与算法Python版学习笔记】树——利用二叉堆实现优先级队列
概念 队列有一个重要的变体,叫作优先级队列. 和队列一样,优先级队列从头部移除元素,不过元素的逻辑顺序是由优先级决定的. 优先级最高的元素在最前,优先级最低的元素在最后. 实现优先级队列的经典方法是使 ...
- 使用加强堆结构解决topK问题
作者:Grey 原文地址: 使用加强堆结构解决topK问题 题目描述 LintCode 550 · Top K Frequent Words II 思路 由于要统计每个字符串的次数,以及字典序,所以, ...
- 纸上谈兵:堆(heap)
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 堆(heap)又被为优先队列(priority queue).尽管名为优先队列,但 ...
- 二叉堆(binary heap)
堆(heap) 亦被称为:优先队列(priority queue),是计算机科学中一类特殊的数据结构的统称.堆通常是一个可以被看做一棵树的数组对象.在队列中,调度程序反复提取队列中第一个作业并运行,因 ...
随机推荐
- 【Azure Function】Function App和Powershell 集成问题, 如何安装PowerShell的依赖模块
问题描述 在Azure Function中创建一个PowerShell的函数后,其中使用了Get-AzMaintenanceUpdate,New-AzApplyUpdate 等指令,但是在执行时错误. ...
- 【Azure 批处理 】Azure Batch门户中创建自定义作业模式失败解决办法
问题描述 跟随官方文档,快速创建Azure批处理任务(快速入门:在 Azure 门户中运行第一个 Batch 作业),在添加作业时,选择"自定义模式",并添加文档中所提供的简单命令 ...
- 一文带你了解 「图数据库」Nebula 的存储设计和思考
本文首发于 Nebula Graph Community 公众号 在上次的 nebula-storage on nLive 直播中,来自 Nebula 存储团队的负责人王玉珏(四王)同大家分享了 ne ...
- 文心一言 VS 讯飞星火 VS chatgpt (209)-- 算法导论15.4 6题
六.设计一个 O(nlgn) 时间的算法,求一个 n 个数的序列的最长单调递增子序列.(提示:注意到,一个长度为 i 的候选子序列的尾元素至少不比一个长度为 i-1 候选子序列的尾元素小.因此,可以在 ...
- debian卡顿,造成用户注销现象的原因以及解决方法
现象:当时电脑正在运行,宝塔面板安装初始化应用,一个浏览器,一个虚拟机 解决方法:目前还不清楚--是不是负载过大?好奇怪!
- 大年学习linux(第一节)
Linux学习笔记 一.常用命令 终端快键键: Ctrl+a/home 切换到命令行开始 Ctrl+e/end 切换到命令行末尾 Ctrl+i 清除屏幕内容,效果等同于clear Ctrl + u 清 ...
- 01.Android线程池实践基础
目录介绍 01.实际开发问题 02.线程池的优势 03.ThreadPoolExecutor参数 04.ThreadPoolExecutor使用 05.线程池执行流程 06.四种线程池类 07.exe ...
- 常用命令--htpasswd--(网站加密)
常用命令htpasswd(网站加密) 常用选项 htpasswd 是一个用于创建和管理HTTP基本认证密码文件的命令行工具,通常与Apache Web服务器一起使用.以下是 htpasswd 常用选项 ...
- [Java]Socket套接字(网络编程入门)
[版权声明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://blog.csdn.net/m0_69908381/article/details/129907893 出自[进步* ...
- 《Effective Java》笔记 4~5
4. 类和接口 15. 使类和成员的可访问性最小化 把API与实现清晰地隔离开,组件间通过API进行通信,不需要知道其他模块的内部工作情况,这称为:实现信息隐藏或封装 解耦系统中的各个组件 尽可能地使 ...