Golang heap堆源码解析

堆作用

Golang 的堆是用二叉树来实现,heap包实现了保证根节点为最大/最小值即大根堆/小根堆,而后续其他的节点顺序不能保证,要想严格排序,需要自行实现额外逻辑。

使用场景

最为经典的场景就是寻找最大或最小值

用法

  1. 实现 heap.Interface接口
  2. 必须使用heap.Init初始化
  3. 必须通过heap.Pushheap.Pop接口来添加删除元素
 var _ heap.Interface = (*hp)(nil)type hp struct {sort.IntSlicedata []int
}func (h *hp) Push(x any) {h.IntSlice = append(h.IntSlice, x.(int))
}func (h *hp) Pop() any {h.IntSlice = h.IntSlice[:len(h.IntSlice)-1]return h.IntSlice[0]
}func (h *hp) Less(i, j int) bool {return h.data[h.IntSlice[i]] > h.data[h.IntSlice[j]]
}func maxSlidingWindow(nums []int, k int) []int {h := &hp{make(sort.IntSlice, k),nums,}for i := 0; i < k; i++ {h.IntSlice[i] = i}heap.Init(h)r := make([]int, 0, len(nums)-k+1)r = append(r, h.data[h.IntSlice[0]])for j := k; j < len(nums); j++ {heap.Push(h, j)for h.IntSlice[0] <= j-k {heap.Pop(h)}r = append(r, h.data[h.IntSlice[0]])}return r
}

核心源码

// Interface 堆的底层数据结构为二叉树
type Interface interface {sort.InterfacePush(x any) // 添加元素Pop() any   // 移除并返回元素
}// Init 方法,初始化后保证父节点和子节点是有序的(不同层数据是有序的)
func Init(h Interface) {// heapifyn := h.Len()for i := n/2 - 1; i >= 0; i-- { // 循环的数据为 除了叶子节点以外所有的节点(保证所有节点都是有序)down(h, i, n)}
}// 插入元素,并把当前元素上浮到合适位置
func Push(h Interface, x any) {h.Push(x)up(h, h.Len()-1)
}// Pop 移除根节点
// 把根节点移到尾部,并把尾部节点下沉到合适位置
func Pop(h Interface) any {n := h.Len() - 1h.Swap(0, n)down(h, 0, n)return h.Pop()
}// Remove 把待删除节点和尾部节点交换,并把尾部节点上浮或者下沉到合适位置
func Remove(h Interface, i int) any {n := h.Len() - 1if n != i {h.Swap(i, n)if !down(h, i, n) {up(h, i)}}return h.Pop()
}// Fix 对于任意节点重新寻找位置(下沉、上浮)
func Fix(h Interface, i int) {if !down(h, i, h.Len()) {up(h, i)}
}// up
//
//	@Description: j 节点 上浮
//	@param h: 堆
//	@param j: 待操作节点
func up(h Interface, j int) {for {i := (j - 1) / 2 // 父节点if i == j || !h.Less(j, i) {break}h.Swap(i, j)j = i}
}// down 方法
//
//	@Description: 当前节点i0 根据大小关系是否下沉(直到叶子节点)
//	@param h: 堆
//	@param i0: 当前待处理节点
//	@param n:节点数量
//	@return bool: 是否进行了下沉
func down(h Interface, i0, n int) bool {i := i0for {j1 := 2*i + 1          // i 的左子节点if j1 >= n || j1 < 0 { // j1 < 0 after int overflow  //保证左子节点存在/有效break}j := j1                                     // left childif j2 := j1 + 1; j2 < n && h.Less(j2, j1) { // j2 为i的右子节点j = j2 // = 2*i + 2  // right child}if !h.Less(j, i) {break}h.Swap(i, j)i = j}return i > i0
}

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

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

相关文章

Unity类银河恶魔城学习记录12-18,19 p140 Options UI-p141 Finalising ToolTip源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI_ToolTip.cs using TMPro; using UnityEngine;public class UI_ToolTip :…

IBM SPSS Statistics for Mac中文激活版:强大的数据分析工具

IBM SPSS Statistics for Mac是一款功能强大的数据分析工具&#xff0c;为Mac用户提供了高效、精准的数据分析体验。 IBM SPSS Statistics for Mac中文激活版下载 该软件拥有丰富的统计分析功能&#xff0c;无论是描述性统计、推论性统计&#xff0c;还是高级的多元统计分析&am…

【面试经典 150 | 链表】K 个一组翻转链表

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;迭代 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容进行回顾…

【从零开始手搓12306项目】第一阶段遇到的问题及解决方案

IDEA中datebase连接mysql失败 读取外包函数报错 注意区分private和public 找不到数据库&#xff1f; 一定要注意数据库的url链接&#xff0c;在datebase的url复制过来 xml和java对应不上&#xff1f; 最好复制一遍到xml文件 git忽略条件文件目录 定义Git全局的 .gitigno…

职业方向与思考

37岁Qt程序员被 裁员 一个 Qt C 程序员的职业生涯_哔哩哔哩_bilibili 纯Qt开发&#xff0c;过于集中在Qt本身&#xff0c;如写界面&#xff0c;写业务&#xff0c;纯APP开发。 可能三五年&#xff0c;你的经验就会有些局限&#xff0c;没有更多的提升。 进一步提升&#xff1…

人工智能与IP代理池:解析网络数据采集的未来

前言 随着互联网的快速发展&#xff0c;数据成为了当今社会最宝贵的资源之一。然而&#xff0c;要获取大量的网络数据并进行有效的分析&#xff0c;往往需要面对诸多挑战&#xff0c;其中之一就是网络封锁与反爬虫机制。在这个背景下&#xff0c;人工智能&#xff08;AI&#x…

Python 物联网入门指南(七)

原文&#xff1a;zh.annas-archive.org/md5/4fe4273add75ed738e70f3d05e428b06 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第二十四章&#xff1a;基本开关 到目前为止一定是一段史诗般的旅程&#xff01;回想一下你开始阅读这本书的时候&#xff0c;你是否曾想象…

IP协议如何进行地址管理?

如今&#xff0c;IP协议有两个版本&#xff0c;分别是IPv4和IPv6&#xff0c;IPv4是目前主要应用的版本。IPv4的IP地址是以4个字节的数字来表示的&#xff0c;比如 127.0.0.1。因此&#xff0c;IPv4所能表示IP地址的个数是2^32次方&#xff0c;也就是42亿多个&#xff0c;看起来…

OpenStack 入门体验

目录 一、云计算概述 1.1、什么是云计算 1.2、云计算的服务模型 1&#xff09;IaaS 2&#xff09;PaaS 3&#xff09;SaaS 1.3、OpenStack 概述 1&#xff09;OpenStack 起源 2&#xff09;什么是 OpenStack 3&#xff09;OpenStack 优势 二、OpenStack 一…

RabbitMQ进阶学习

在之前的练习作业中&#xff0c;我们改造了余额支付功能&#xff0c;在支付成功后利用RabbitMQ通知交易服务&#xff0c;更新业务订单状态为已支付。 但是大家思考一下&#xff0c;如果这里MQ通知失败&#xff0c;支付服务中支付流水显示支付成功&#xff0c;而交易服务中的订…

mariadb 添加新用户,并给新用户对应权限

在MariaDB中添加新用户并为该用户添加相应权限&#xff0c;可以按照以下步骤进行操作&#xff1a; 登录MariaDB数据库服务器&#xff1a; mysql -u root -p输入管理员用户名和密码进行登录。 创建新用户&#xff1a; CREATE USER new_userlocalhost IDENTIFIED BY password;将…

IAM 统一身份认证与访问管理服务

即统一身份认证与访问管理服务&#xff0c;是云服务商提供的一套云上身份管理解决方案&#xff0c;可帮助企业安全地管理云上资源的访问权限。 在当今云计算时代&#xff0c;企业越来越依赖云服务来存储和处理敏感数据。然而&#xff0c;这也带来了新的安全挑战&#xff0c;即…

CentOS:执行make命令时报错g++: Command not found

报错截图&#xff1a; 其实很简单只需要安装一下 yum -y install gcc automake autoconf libtool make yum install gcc gcc-c

RabbitMQ交换机的类型

交换机类型 可以看到&#xff0c;在订阅模型中&#xff0c;多了一个exchange角色&#xff0c;而且过程略有变化&#xff1a; Publisher&#xff1a;生产者&#xff0c;不再发送消息到队列中&#xff0c;而是发给交换机 Exchange&#xff1a;交换机&#xff0c;一方面&#xff…

OSPF大型实验

OSPF大型实验 实验拓扑图 实验思路 1、R4为ISP&#xff0c;其上只配置IP地址&#xff1b;R4与其他所直连设备间均使用公有IP&#xff1b; 2、R3-R5、R6、R7为MGRE环境&#xff0c;R3为中心站点&#xff1b; 3、整个OSPF环境IP基于172.16.0.0/16划分&#xff1b;除了R12有两…

初识数据库与数据库管理系统

实体的概念与数据库 实体(对象): 客观存在的事物都是实体实体数据的存储要求: 必须按照一定的分类和规律存储数据库: 专门用于存储这些实体的信息的数据集合数据库的特点: 海量存储数据&#xff0f;数据检索非常方便保持数据信息的一致&#xff0f;完整&#xff0f;并实现数据…

通过 Ollama、Langchain 实现 RAG

RAG 是什么 RAG 在 Langchain 上的定义是&#xff0c;作为大语言模型最常用的场景就是问答系统&#xff0c;可以针对特别来源数据做问题回答&#xff0c;就是私有数据&#xff0c;这就是 RAG&#xff0c;英文全称是Retrieval Augmented Generation。就是对现有模型数据的增广&…

如何使用cuda进行图像矫正

普通矫正 相机矫正我们经常会用到&#xff0c;如果没有gpu加速&#xff0c;实际上矫正会很吃力&#xff0c;我们先用普通的矫正 cv::Mat undistort(cv::Mat img, cv::Mat K, cv::Mat D, int w, int h, float scale 0.6){cv::Mat Knew K.clone();//Knew K.copy()if (scale !…

解决向MySQL中导入文件中的 数据时出现的问题~

SQL语句如下所示&#xff1a; load data infile C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/data1.txt into table user fields terminated by , lines terminated by "\n" (name,sex,age,address,email,id,phone);报错1&#xff1a; The MySQL server is run…

Spring Boot 实现定时任务

前言 在实际开发中,我们经常需要处理一些周期性或定时的任务,比如每天凌晨进行数据统计、报表生成,或者每隔一段时间清理缓存等。Spring Boot 集成了 Quartz 和 Spring 自带的 TaskScheduler 等多种定时任务框架,使得实现定时任务变得非常方便。本文将通过一个详细的示例,…