【数据结构】手写堆 HEAP

heap【堆】掌握

  • 手写上浮、下沉、建堆函数

  • 对一组数进行堆排序

  • 直接使用接口函数heapq

什么是堆???堆是一个二叉树。也就是有两个叉。下面是一个大根堆:

大根堆的每一个根节点比他的子节点都大

有大根堆就有小根堆:

我们可以看到红9在绿9的下一层,大小堆中我们需要注意,【只有根节点对子节点的大小比较】,没有子节点之间的比较。

一、手写函数

def siftup(heap, pos):endpos = len(heap)startpos = posnewitem = heap[pos]# Bubble up the smaller child until hitting a leaf.childpos = 2*pos + 1    # leftmost child positionwhile childpos < endpos:# Set childpos to index of smaller child.rightpos = childpos + 1if rightpos < endpos and not heap[childpos] < heap[rightpos]:childpos = rightpos# Move the smaller child up.heap[pos] = heap[childpos]pos = childposchildpos = 2*pos + 1# The leaf at pos is empty now.  Put newitem there, and bubble it up# to its final resting place (by sifting its parents down).heap[pos] = newitem'''up操作只是将孩子提上去,但是没有保证根节点比孩子小,现在比较孩子和父节点,如果父节点更大,往下覆盖孩子节点,并且往上继续,比较上面的父节点,直至到头start,将原来的子节点的值覆盖在此时的父节点上。'''siftdown(heap, startpos, pos)'''up与down一起维持小根堆性质'''
def siftdown(heap, startpos, pos):newitem = heap[pos]# Follow the path to the root, moving parents down until finding a place# newitem fits.while pos > startpos:parentpos = (pos - 1) >> 1parent = heap[parentpos]if newitem < parent:heap[pos] = parentpos = parentposcontinuebreakheap[pos] = newitemdef heappop(heap):"""Pop the smallest item off the heap, maintaining the heap invariant."""lastelt = heap.pop()    # raises appropriate IndexError if heap is emptyprint('pop:', lastelt)if heap:returnitem = heap[0]heap[0] = lasteltsiftup(heap, 0)print('heap:', heap)print('returnitem', returnitem)return returnitemreturn lasteltdef heapify(x):"""Transform list into a heap, in-place, in O(len(x)) time."""n = len(x)for i in reversed(range(n//2)):'''从最后一个根节点开始,将孩子节点最小的覆盖根节点,并不断往下找,将较小的孩子提上来。直到没有孩子,将根节点的值覆盖到此时的孩子节点上'''siftup(x, i)def heap_sort(arr):# 将数组转换为小根堆heapify(arr)print(arr)# 弹出堆顶元素直到堆为空'''每次pop最后一个节点,并输出根节点。将最后一个节点覆盖在根节点上,并且进行up——down操作位置小根堆性质'''return [heappop(arr) for _ in range(len(arr))]if __name__ == '__main__':# 示例数组arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]# 执行堆排序sorted_arr = heap_sort(arr)# 打印排序后的数组print('sorted_arr', sorted_arr)

二、调用python接口

import heapq
def heap_sort(arr):# 将数组转换为小根堆heapq.heapify(arr)print(arr)# 弹出堆顶元素直到堆为空'''每次pop最后一个节点,并输出根节点。将最后一个节点覆盖在根节点上,并且进行up——down操作位置小根堆性质'''return [heapq.heappop(arr) for _ in range(len(arr))]if __name__ == '__main__':# 示例数组arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]# 执行堆排序sorted_arr = heap_sort(arr)# 打印排序后的数组print('sorted_arr', sorted_arr)

输出:

[1, 1, 2, 3, 3, 9, 4, 6, 5, 5, 5]
sorted_arr [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]

三、时间复杂度

O(NlogN)

  1. siftup(heap, pos) 函数:

    • 这个函数将一个元素上浮到它应该在的位置。在最坏的情况下,它可能需要上浮到堆的根节点,时间复杂度是 O(log n),其中 n 是堆中元素的数量。
  2. siftdown(heap, startpos, pos) 函数:

    • 这个函数将一个元素下沉到它应该在的位置。同样,在最坏的情况下,它可能需要下沉到叶子节点,时间复杂度也是 O(log n)。
  3. heappop(heap) 函数:

    • 这个函数移除并返回堆顶元素(最小元素),然后通过调用 siftup 来修复堆。siftup 的时间复杂度是 O(log n),所以 heappop 的时间复杂度也是 O(log n)。
  4. heapify(x) 函数:

    • 这个函数将一个数组转换成一个堆。它从最后一个父节点开始,向上调用 siftup。由于堆的最后一个父节点的索引是 n/2 - 1(n 是数组的长度),所以它实际上调用了大约 n/2 次 siftup。因此,heapify 的时间复杂度是 O(n)。
  5. heap_sort(arr) 函数:

    • 这个函数首先调用 heapify 将数组转换成一个堆,然后通过 n 次调用 heappop 来移除所有元素。由于 heapify 的时间复杂度是 O(n),并且 heappop 的时间复杂度是 O(log n),heap_sort 的总时间复杂度是 O(n log n)。

总结:

  • 时间复杂度:
    • siftup: O(log n)
    • siftdown: O(log n)
    • heappop: O(log n)
    • heapify: O(n)
    • heap_sort: O(n log n)

整体上,对于堆排序算法的时间复杂度分析如下

  • 构建堆(Heapify)heapify 函数将数组转换成一个堆。对于一个长度为 n 的数组,heapify 的时间复杂度是 O(n)。这是通过从最后一个父节点开始,向上调用 siftup 实现的,每个 siftup 操作的时间复杂度是 O(log n),但由于堆的结构特性,实际上 heapify 的总体时间复杂度是线性的。

  • 堆排序(Heap Sort):在 heap_sort 函数中,首先调用 heapify 将数组转换成一个堆,然后通过 n 次调用 heappop 来移除所有元素。每次 heappop 操作的时间复杂度是 O(log n)。因此,n 次 heappop 的总时间复杂度是 O(n log n)。

  • 综合以上两点,堆排序的整体时间复杂度是 O(n + n log n),简化后为 O(n log n)。这是因为在堆排序过程中,构建堆是一次性的,而移除元素需要 n 次操作,每次操作的复杂度是 log n。

  • 空间复杂度:O(1),因为所有操作都是原地进行的。

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

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

相关文章

(南京观海微电子)——二极管应用及选取

二极管是 用半导体材料(硅、硒、锗等)制成的一种电子器件。二极管有两个电极&#xff0c;正极&#xff0c;又叫阳极&#xff1b;负极&#xff0c;又叫阴极&#xff0c;给二极管两极间加上正向电压时&#xff0c;二极管导通&#xff0c; 加上反向电压时&#xff0c;二极管截止。…

Vue1-Vue核心

目录 Vue简介 官网 介绍与描述 Vue的特点 与其它 JS 框架的关联 Vue周边库 初识Vue Vue模板语法 数据绑定 el与data的两种写法 MVVM模型 数据代理 回顾Object.defineProperty方法 何为数据代理 Vue中的数据代理 数据代理图示 事件处理 事件的基本使用 事件修…

【UE5.1】Chaos物理系统基础——06 子弹破坏石块

前言 在前面我们已经完成了场系统的制作&#xff08;【UE5.1】Chaos物理系统基础——02 场系统的应用_ue5&#xff09;以及子弹的制作&#xff08;【UE5.1 角色练习】16-枪械射击——瞄准&#xff09;&#xff0c;现在我们准备实现的效果是&#xff0c;角色发射子弹来破坏石柱。…

STM32智能空气质量监测系统教程

目录 引言环境准备智能空气质量监测系统基础代码实现&#xff1a;实现智能空气质量监测系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;空气质量监测与优化问题解决方案与优化收尾与总结 1. 引言 智能空…

基于Java+SpringMvc+Vue技术的药品进销存仓库管理系统设计与实现系统(源码+LW+部署讲解)

注&#xff1a;每个学校每个老师对论文的格式要求不一样&#xff0c;故本论文只供参考&#xff0c;本论文页数达到60页以上&#xff0c;字数在6000及以上。 基于JavaSpringMvcVue技术的在线学习交流平台设计与实现 目录 第一章 绪论 1.1 研究背景 1.2 研究现状 1.3 研究内容…

卸载wps office的几种方法收录

​ 第一种方法: 1.打开【任务管理器】&#xff0c;找到相关程序&#xff0c;点击【结束任务】。任务管理器可以通过左下角搜索找到。 2.点击【开始】&#xff0d;【设置】&#xff0d;【应用】&#xff0d;下拉找到WPS应用&#xff0c;右键卸载&#xff0c;不保留软件配置 …

Git学习1_Git安装(CSDN_20240714)

git下载 git下载官网如下&#xff1a; Git - Downloads (git-scm.com)https://git-scm.com/downloads 根据机器操作系统&#xff0c;下载对应的安装包 git安装 1. 点击安装程序&#xff0c;进入安装界面&#xff0c;如下图所示&#xff0c;点击next。 2. 选择安装路径&…

护网HW面试常问——组件中间件框架漏洞(包含流量特征)

apache&iis&nginx中间件解析漏洞 参考我之前的文章&#xff1a;护网HW面试—apache&iis&nginx中间件解析漏洞篇-CSDN博客 log4j2 漏洞原理&#xff1a; 该漏洞主要是由于日志在打印时当遇到${后&#xff0c;以:号作为分割&#xff0c;将表达式内容分割成两部…

Leetcode(经典题)day2

H指数 274. H 指数 - 力扣&#xff08;LeetCode&#xff09; 先对数组排序&#xff0c;然后从大的一头开始遍历&#xff0c;只要数组当前的数比现在的h指数大就给h指数1&#xff0c;直到数组当前的数比现在的h指数小的时候结束&#xff0c;这时h的值就是要返回的结果。 排序…

下载安装nodejs npm jarn笔记

下载安装nodejs npm jarn笔记 下载 Node.js安装Node.js修改node全局路径安装yarn 下载 Node.js 下载Node.js 安装Node.js 双击下载的下来的.msi文件运行并安装一直点next。安装路径可以是默认也可自定义。安装完成后Node.js和npm就安装完成了 命令行输入&#xff1a; nod…

LeetCode 面试题02.04.分割链表

LeetCode 面试题02.04.分割链表 C写法 思路&#x1f914;&#xff1a; ​ 将x分为两段&#xff0c;一段放小于x的值&#xff0c;另一段放大于x的值。开辟四个指针lesshead、lesstail、greaterhead、greatertail&#xff0c;head为哨兵位&#xff0c;防止链表为空时情况过于复杂…

推荐一款 uniapp Vaptcha 手势验证码插件

插件地址&#xff1a;VAPTCHA手势验证码 - DCloud 插件市场 具体使用方式可访问插件地址自行查阅

Vue从零到实战

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

WEB前端03-CSS3基础

CSS3基础 1.CSS基本概念 CSS是Cascading Style Sheets&#xff08;层叠样式表&#xff09;的缩写&#xff0c;它是一种对Web文档添加样式的简单机制&#xff0c;是一种表现HTML或XML等文件外观样式的计算机语言&#xff0c;是一种网页排版和布局设计的技术。 CSS的特点 纯C…

R语言安装devtools包失败过程总结

R语言安装devtools包时&#xff0c;遇到usethis包总是安装失败&#xff0c;现总结如下方法&#xff0c;亲测可有效 一、usethis包及cli包安装问题 首先&#xff0c;Install.packages("usethis")出现如下错误&#xff0c;定位到是这个cli包出现问题 载入需要的程辑包…

永磁同步电机控制算法--基于 SVM 的无磁链环 DTC

永磁同步电机无磁链环 DTC 通过控制定子磁链交轴分量来直接控制转矩&#xff0c;不再要求控制磁链幅值恒定&#xff0c;省去了传统 DTC 中的磁链环&#xff0c;不仅转矩响应更快&#xff0c;有效抑制了转矩脉动&#xff0c;而且提高了电机功率因数。但无磁链环 DTC 方案仍采用传…

YOWOv2(yowov2)动作识别+Fastreid身份识别 详细安装与实现

首先yowov2是一款简单且实时的时空动作检测方案&#xff0c;fastreid是行人重识别&#xff08;身份识别&#xff09; yowov2介绍链接直达fastreid链接直达为时空动作检测任务设计实时框架仍然是一个挑战。YOWOv2 提出了一种新颖的实时动作检测框架&#xff0c;利用三维骨干和二…

【Js】导出 HTML 为 Word 文档

在 Web 开发中&#xff0c;有时我们希望用户能够将网页上的 HTML 内容保存为 Word 文档&#xff0c;以便更方便地分享和打印。 html样式 word文档 工具准备 1、 html-docx-js - npm html-docx-js是一个 JavaScript 库&#xff0c;用于将 HTML 内容转换为 Word 文档的格式。它…

在Linux系统实现瑞芯微RK3588部署rknntoolkit2进行模型转换

一、首先要先安装一个虚拟的环境 安装Miniconda包 Miniconda的官网链接:Minidonda官网 下载好放在要操作的linux系统,我用的是远程服务器的linux系统,我放在whl这个文件夹里面,这个文件夹是我自己创建的 运行安装 安装的操作都是yes就可以了 检查是否安装成功,输入下面…

【CEEMDAN-VMD-CNN-LSTM】双重分解+卷积神经网络+长短期记忆神经网络多变量回归预测,多变量输入模型

双重分解&#xff08;Dual Decomposition&#xff09;、卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;和长短期记忆神经网络&#xff08;Long Short-Term Memory&#xff0c;LSTM&#xff09;结合的多变量回归预测需要详细的实现和数据情况…