堆算法详解

目录

二叉堆的实现

二叉堆的插入

二叉堆取出堆顶 (extract/delete max)

优先对列 (priority queue)

堆的实现

语言中堆的实现

leadcode 题目堆应用


堆是一种高效维护集合中最大或最小元素的数据结构。

大根堆:根节点最大的堆,用于维护和查询max。

小根堆:根节点最小的堆,用于维护和查询min

堆是一棵树,并且满足堆特质:大根堆任意节点的关键码 >= 它所有子节点的关键码 (父>=子)。小根堆任意节点的关键码<=它所有子节点的关键码 (父<=子)

二叉堆除了满足堆的性质外,它还必须是一棵完全二叉树

常见的操作时间复杂度

建堆:O(N)、查询最值(get max/min) O(1) 、插入O(logN)、取出最值 (delete max/min) O(logN)

二叉堆的实现

假设第一个元素存储在索引(下标)为1的位置的话,这个节点计作p,那么它的左孩子的索引下标是 p2, 右孩子的索引下标是2p+1,那么p节点的父节点为p/2(下取整)

假设第一个元素存储在索引(下标)为0的位置的话,这个节点计作p,那么它的左孩子的索引下标是 p2+1, 右孩子的索引下标是2p+2,那么p节点的父节点为(p-1/2)(下取整)

根据这个特点我们可以用一维数组存储二叉堆

二叉堆的插入

新元素一律插入到数组heap 的尾部,这个点设置成p,然后向上进行一次调整 (heapify up)

若此时已经到达根,就停止。若满足堆性质 (heap[p]<=heap[p/2]) 停止,否则交换 heap[p] 和 heap[p/2] 令 p=p/2 继续调整

时间复杂度是 O(logN)

二叉堆取出堆顶 (extract/delete max)

把堆顶(heap[1)和 堆尾 (heap[n]) 交换,删除堆尾部 (删除最后一个元素) 然后从根向下进行一个调整(heapify Down) 每次与左右子节点中较大的一个比较,检查堆性质,不满足则交换,注意判定子节点是否存在 那么时间复杂度是O(logN)

优先对列 (priority queue)

二叉堆是优先队列一种简单、常见的实现,但不是最优实现 理论上二叉堆可以支持O(logN) 删除任意元素,只需要 定位该元素在堆中的节点p(可以通过数值与索引之间建立映射得倒) 与堆尾交换,删除堆尾。从p向上、向下各进行一次调整 不过优先队列并没有提供这个方法 在各语言内置的库中,需要支持删除任意元素时,一般使用有序集合等基于平衡二叉搜索树的实现

堆的实现

type heapList []int
​
func (h *heapList) insertVal(val int) {*h = append(*h, val)h.shiftUp(len(*h) - 1)
}
​
func (h *heapList) shiftUp(index int) {for index >= 0 {pInde := index / 2if (*h)[pInde] > (*h)[index] {(*h)[pInde], (*h)[index] = (*h)[index], (*h)[pInde]}index--}
}
​
func (h *heapList) Pop() int {val := (*h)[0](*h)[0] = (*h)[len(*h)-1]*h = (*h)[:len(*h)-1]h.shiftDown(0)h.shiftUp(len(*h) - 1)return val
}
​
func (h *heapList) shiftDown(index int) {hLen := len(*h) - 1for index <= hLen {iL := index*2 + 1if iL+1 <= hLen && (*h)[iL+1] < (*h)[iL] {iL += 1}if iL <= hLen && (*h)[iL] < (*h)[index] {(*h)[iL], (*h)[index] = (*h)[index], (*h)[iL]}index = iL}
}

语言中堆的实现

type li []int
​
func (l li) Len() int {return len(l)
}
​
func (l li) Swap(i, j int) {l[i], l[j] = l[j], l[i]
}
​
func (l li) Less(i, j int) bool {return l[i] > l[j]
}
​
func (l *li) Push(val interface{}) {*l = append(*l, val.(int))
}
​
func (l *li) Pop() interface{} {len_l := len(*l)val := (*l)[len_l-1](*l) = (*l)[:len_l-1]return val
}
​
func main() {var list = &li{}heap.Init(list)heap.Push(list, 1)heap.Push(list, 100)heap.Push(list, 50)heap.Push(list, 150)fmt.Println(heap.Pop(list))fmt.Println(heap.Pop(list))fmt.Println(heap.Pop(list))
}

leadcode 题目堆应用

23. 合并 K 个升序链表

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 1:

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[1->4->5,1->3->4,2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
/*** Definition for singly-linked list.* type ListNode struct {*     Val int*     Next *ListNode* }*/type heapList []*ListNode
​func (t *heapList) insertNode(node *ListNode){*t = append(*t,node)t.shiftup(len(*t)-1)}
​func (t *heapList) shiftup(index int){for index>=0{pIndex:=index/2if (*t)[pIndex].Val>(*t)[index].Val{(*t)[pIndex],(*t)[index] = (*t)[index],(*t)[pIndex]}index--}}
​func (t *heapList) Pop() *ListNode{val:=(*t)[0](*t)[0] = (*t)[len(*t)-1]*t = (*t)[:len(*t)-1]t.ShiftDown(0)t.shiftup(len(*t)-1)return val}
​func (t *heapList) ShiftDown(index int){hLen:=len(*t)-1for index<=hLen{Lindex:=2*index+1if Lindex+1<=hLen && (*t)[Lindex].Val>(*t)[Lindex+1].Val{Lindex+=1}if Lindex<=hLen && (*t)[Lindex].Val<(*t)[index].Val{(*t)[Lindex],(*t)[index] = (*t)[index],(*t)[Lindex]}index = Lindex}}
​
func mergeKLists(list []*ListNode) *ListNode {heap:= &heapList{}for _,v:=range list{if v==nil{continue}heap.insertNode(v)}head:=&ListNode{}temp:=headfor len(*heap)>0{node:=heap.Pop()temp.Next = nodetemp = temp.Nextif node.Next!=nil{heap.insertNode(node.Next)}}return head.Next
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/846648.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C/C++开发,2024.x CLion安装,亲测有效

CLion 是一款专为 C 和 C 开发者设计的跨平台集成开发环境&#xff08;IDE&#xff09;&#xff0c;提供了智能代码补全、代码分析、调试和 Git 集成等功能&#xff0c;以提高开发效率和代码质量。 1.下载安装c/c开发工具 CLion 先去官网下载&#xff0c;我这里下载的是最新版…

装修全流程

Summary 从2023年底到现在&#xff08;2024年6月2日&#xff09;&#xff0c;装修可以定的东西基本过半了&#xff0c;我按照时间顺序把每个环节的内容和想法都记录一下 环节 选装修公司、找设计师设计环节预算计算角色介绍建材选型敲墙和开工水电放样泥工木工放样To be cont…

Re73 读论文:ULMFiT Universal Language Model Fine-tuning for Text Classification

诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文全名&#xff1a;Universal Language Model Fine-tuning for Text Classification 模型简称&#xff1a;ULMFiT 模型全名&#xff1a;Universal Language Model Fine-tuning ArXiv网址&#xff1a;https…

20240529每日前端--------vue数组对象包含数组,判断子数组是否有重复对象

数组格式如下&#xff1a; "industrySceneList": [{"mainIndustry": 1,"mainIndustryName": "林草","sceneList": [{"subIndustry": 1,"subIndustryName": "森林防火"}]},{"mainIndust…

【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版6(附带项目源码)

最终效果 系列导航 文章目录 最终效果系列导航前言方法一、使用excel配置表excel转txt文本读取txt数据按配置信息生成僵尸 方法二、使用ScriptableObject 配置关卡信息源码结束语 前言 本节主要是推荐两种实现配置关卡信息&#xff0c;并按表生成僵尸和关卡波次 方法一、使用…

PCIe总线-事物层之TLP路由介绍(七)

1.概述 下图是一个PCIe总线系统示意图。此时RC发出一个TLP&#xff0c;经过Switch访问EP&#xff0c;TLP的路径为红色箭头所示。首先TLP从RC的下行OUT端口发出&#xff0c;Switch的上行IN端口接收到该TLP后&#xff0c;根据其路由信息&#xff0c;将其转发到Switch的下行OUT端…

领域驱动设计(DDD)学习笔记之:基础理论与概念

DDD基础概念 领域、子域和限界上下文 在领域驱动设计&#xff08;DDD&#xff09;中&#xff0c;领域、子域和限界上下文是基础的概念&#xff0c;它们帮助我们理解和组织复杂的业务系统。以下是对这些概念的详细讲解&#xff1a; 1. 领域&#xff08;Domain&#xff09; 定…

AI学习指南机器学习篇-线性回归在python中的实现sklearn

AI学习指南机器学习篇-线性回归在python中的实现sklearn 在机器学习领域中&#xff0c;线性回归是最为基础和常见的模型之一。它被广泛应用于预测和建模等领域&#xff0c;是我们学习机器学习的不二选择。 本篇博客将详细介绍如何使用Python中的sklearn库来实现一元和多元线性…

Google力作 | Infini-attention无限长序列处理Transformer

更多文章&#xff0c;请关注微信公众号&#xff1a;NLP分享汇 原文链接&#xff1a;Google力作 | Infini-attention无限长序列处理Transformerhttps://mp.weixin.qq.com/s?__bizMzU1ODk1NDUzMw&mid2247485000&idx1&sne44a7256bcb178df0d2cc9b33c6882a1&chksm…

MySQL 连接池在 Python 中的深度探索与实践

MySQL 连接池在 Python 中的深度探索与实践 在 Python 中&#xff0c;高效地管理数据库连接是一个关键任务&#xff0c;尤其是在处理大量并发请求时。MySQL 连接池作为优化数据库连接管理的工具&#xff0c;显得尤为重要。本文将从四个方面、五个方面、六个方面和七个方面&…

Linux的shell脚本:如何用bash脚本从mysql数据库中直接读取用户数据,并直接显示出来(一条命令查看数据库信息)

目录 一、要求 二、脚本和解释 三、脚本执行 1、 脚本保存为sh文件 2、给脚本赋予执行权限 3、运行脚本 四、Bash脚本中&#xff0c;可以使用哪些MySQL语句 1、连接到MySQL数据库 2、执行SQL语句 3、查询并显示结果 4、脚本中执行SQL文件 5、数据库操作 …

conda源不能用了的问题

conda旧没用了&#xff0c;不知道什么原因&#xff0c;安装源出问题&#xff0c;报如下错&#xff1a; Loading channels: failedUnavailableInvalidChannel: HTTP 404 NOT FOUND for channel anaconda/pkgs/main <https://mirrors.aliyun.com/anaconda/pkgs/main>The c…

Vue.js 动态组件与异步组件

title: Vue.js 动态组件与异步组件 date: 2024/6/2 下午9:08:50 updated: 2024/6/2 下午9:08:50 categories: 前端开发 tags:Vue概览动态组件异步加载性能提升路由管理状态控制工具生态 第1章 Vue.js 简介 1.1 Vue.js 概述 Vue.js 是一个渐进式的JavaScript框架&#xff0c;…

6.2数据库作业

文章目录 11.11.21.3 22.12.2 33.13.23.3 4 1 1.1 丢失更新(lost update)异常是指如果事务Tj读取了一个数据项&#xff0c;然后另一个事务Ti写该数据项(可能基于先前的读取)&#xff0c;然后Tj写该数据项。于是Ti做的更新丢失了&#xff0c;因为Tj的更新覆盖了Ti写入的值。 给…

JAVA基础(4) 面向对象编程1

目录 一、面向对象编程概述 1.面向对象的程序设计思想 二、JAVA语言的基本元素&#xff1a;类和对象 1.类为何物&#xff1f; 2.对象为何物&#xff1f; 3.类的成员 4.如何完成面向对象&#xff1f; 三、类的成员——变量 1.如何声明变量 2.成员变量与局部变量 四、…

大模型时代的向量数据库

向量数据库专门用于存储和处理向量数据。它的能够高效地存储和检索向量数据&#xff0c;使开发者能够进行高级的相似性搜索和分析。 在大模型时代&#xff0c;文本、图像、音频和其他非结构化数据&#xff0c;通常被嵌入到一定维度的向量空间&#xff0c;使用向量数据库能够高效…

《论文阅读》通过顺序不敏感的表示正则化实现稳健的个性化对话生成 ACL 2023

《论文阅读》通过顺序不敏感的表示正则化实现稳健的个性化对话生成 ACL 2023 前言 相关个性化生成论文推荐简介问题定义方法损失函数实验结果 前言 亲身阅读感受分享&#xff0c;细节画图解释&#xff0c;再也不用担心看不懂论文啦~ 无抄袭&#xff0c;无复制&#xff0c;纯手…

中间件模版引擎

文章目录 中间件1.自定义中间件1&#xff09;全局2&#xff09;局部中间件 2.内置中间件(静态资源目录&#xff09; Art-template1.模板语法1&#xff09;输出2&#xff09;原文输出3&#xff09;条件判断4&#xff09;循环5&#xff09;子模版6&#xff09;模版继承7&#xff…

vue-Dialog 自定义title样式

展示结果 vue代码 <el-dialog :title"title" :visible.sync"classifyOpen" width"500px" :showClose"false" class"aboutDialog"> <el-form :model"classifyForm" :rules"classifyRules">…

【OJ】C++ | 二叉树进阶 · 合集(2)

摘要&#xff1a;根据二叉树创建字符串、二叉树的最近公共祖先、二叉树的层序遍历 前言&#xff1a;承接上文&#xff0c;本文继续提供二叉树进阶有关题目的解法。如有错误&#xff0c;烦请指正。 目录 1. 根据二叉树创建字符串 题解及代码 2. 二叉树的最近公共祖先 题解及…