【数据结构】手写堆 HEAP

heap【堆】掌握

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

  • 对一组数进行堆排序

  • 直接使用接口函数heapq

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

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

有大根堆就有小根堆:

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

一、手写函数

def siftup(heap, pos):
    endpos = len(heap)
    startpos = pos
    newitem = heap[pos]
    # Bubble up the smaller child until hitting a leaf.
    childpos = 2*pos + 1    # leftmost child position
    while childpos < endpos:
        # Set childpos to index of smaller child.
        rightpos = childpos + 1
        if rightpos < endpos and not heap[childpos] < heap[rightpos]:
            childpos = rightpos
        # Move the smaller child up.
        heap[pos] = heap[childpos]
        pos = childpos
        childpos = 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) >> 1
        parent = heap[parentpos]
        if newitem < parent:
            heap[pos] = parent
            pos = parentpos
            continue
        break
    heap[pos] = newitem

def heappop(heap):
    """Pop the smallest item off the heap, maintaining the heap invariant."""
    lastelt = heap.pop()    # raises appropriate IndexError if heap is empty
    print('pop:', lastelt)
    if heap:
        returnitem = heap[0]
        heap[0] = lastelt
        siftup(heap, 0)
        print('heap:', heap)
        print('returnitem', returnitem)
        return returnitem
    return lastelt

def 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),因为所有操作都是原地进行的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构(4.1)——串的存储结构

串的顺序存储 串&#xff08;String&#xff09;的顺序存储是指使用一段连续的存储单元来存储字符串中的字符。 计算串的长度 静态存储(定长顺序存储) #define MAXLEN 255//预定义最大串为255typedef struct {char ch[MAXLEN];//每个分量存储一个字符int length;//串的实际长…

YOLOv8-OBB 旋转目标检测训练自己的数据

数据集制作 标注工具&#xff1a;X-AnyLabeling https://github.com/CVHub520/X-AnyLabeling 下载链接&#xff1a;https://pan.baidu.com/s/1UsnDucBDed8pU1RtaVZhQw?pwd5kel 数据标注可以参考&#xff1a;https://zhuanlan.zhihu.com/p/665036259 1. 选择导出方式为…

Ubuntu搭建Android架构so库交叉编译环境

目录 前言一、下载NDK并安装二、安装NDK三、配置交叉编译工具链四、编写交叉编译脚本 前言 需要将一些源码编译成Android可用的架构的so库 一、下载NDK并安装 https://developer.android.google.cn/ndk/downloads/ 二、安装NDK 将下载下来的android-ndk-r23b-linux.zip解压…

[GICv3] 3. 物理中断处理(Physical Interrupt Handling)

中断生命周期 ​​ 外设通过中断信号线生成中断&#xff0c;或者软件生成中断&#xff08;SGI&#xff09;。Distributor 和 ReDistributor 配合按照中断分组和中断优先级仲裁后将最高优先级的中断分发到 CPU interface。cpu interface 向中断发送到 PEPE 读取 IAR 寄存器&am…

力扣 24两两交换链表中节点

画图 注意有虚拟头结点 注意判断时先判断cur->next ! nullptr,再判断cur->next->next ! nullptr 注意末尾返回dumyhead->next&#xff0c;用新建result指针来接并返回 class Solution { public:ListNode* swapPairs(ListNode* head) {ListNode *dummyhead new …

高等数学第一讲:函数极限与连续

函数极限与连续 文章目录 函数极限与连续1.函数概念与特性1.1 函数定义 1.2 几种重要的基本函数类型1.2.1 反函数1.2.2 复合函数1.2.3 隐函数 1.3 函数的基本特性1.3.1 有界性1.3.2 单调性1.3.3 奇偶性1.3.4 周期性 2. 函数的极限2.1函数的极限的定义2.2 函数的极限的性质2.3 无…

昇思25天学习打卡营第19天|基于MindNLP+MusicGen生成自己的个性化音乐

MusicGen是来自Meta AI的Jade Copet等人提出的基于单个语言模型&#xff08;LM&#xff09;的音乐生成模型&#xff0c;能够根据文本描述或音频提示生成高质量的音乐样本&#xff0c;相关研究成果参考论文《Simple and Controllable Music Generation》。 MusicGen模型基于Tra…

LabVIEW液压数据采集测试系统

液压系统是装载机的重要组成部分&#xff0c;通过液压传动和控制实现各项作业功能&#xff0c;如提升、倾斜、转向等。液压系统的性能直接影响装载机的作业效率和稳定性。为了保证装载机液压系统的正常运行和优化设计&#xff0c;需要对其进行数据采集和测试。本文介绍了一套基…

jQuery代码原封不动的显示在网页中,应该是没有放在script标签中

jQuery代码原封不动的显示在网页中&#xff0c; 应该是没有放在script标签中 <body> <span id"a1">I am a element by id is a1</span>$(#a1).attr({name:spanDom,title:a1Title}); alert($(#a1).attr(id));alert($(#a1).attr(name));alert($(#a1…

企业网三层架构

企业网三层架构&#xff1a;是一种层次化模型设计&#xff0c;旨在将复杂的网络设计分成三个层次&#xff0c;每个层次都着重于某些特定的功能&#xff0c;以提高效率和稳定性。 企业网三层架构层次&#xff1a; 接入层&#xff1a;使终端设备接入到网络中来&#xff0c;提供…

昇思25天学习打卡营第20天 | 基于MindNLP+MusicGen生成自己的个性化音乐

基于MindNLPMusicGen生成个性化音乐 实验简介 MusicGen是Meta AI提出的音乐生成模型&#xff0c;能够根据文本描述或音频提示生成高质量音乐。该模型基于Transformer结构&#xff0c;分为三个阶段&#xff1a;文本编码、音频token预测和音频解码。此实验将演示如何使用MindSpo…

【JavaEE】AOP实现原理

概述 Spring AOP 是基于动态代理来实现AOP的, 此处主要介绍代理模式和Spring AOP的源码剖析 一.代理模式 代理模式是一种常用的设计模式&#xff0c;它允许为其他对象提供代理&#xff0c;以控制对这个对象的访问。这种结构在不改变原始类的基础上&#xff0c;通过引入代理类…

CentOS 7:停止更新后如何下载软件?

引言 CentOS 7 是一个广受欢迎的 Linux 发行版&#xff0c;它为企业和开发者提供了一个稳定、安全、且免费的操作系统环境。然而&#xff0c;随着时间的推移&#xff0c;CentOS 7 的官方支持已经进入了维护阶段&#xff0c;这意味着它将不再收到常规的更新和新功能&#xff0c;…

「网络通信」HTTP 协议

HTTP &#x1f349;简介&#x1f349;抓包工具&#x1f349;报文结构&#x1f34c;请求&#x1f34c;响应&#x1f34c;URL&#x1f95d;URL encode &#x1f34c;方法&#x1f34c;报文字段&#x1f95d;Host&#x1f95d;Content-Length & Content-Type&#x1f95d;User…

千帆模型申请方法

第一步&#xff1a;注册千帆云账号 百度智能云-云智一体深入产业 第二步&#xff1a;申请实名认证 第三步&#xff1a;开通服务 第四步&#xff1a;配置到网方Ai的设置里去&#xff0c;网方Ai的下载地址见下面链接。 网方Ai的软件下载地址见论坛地址&#xff1a; 网创有方官…

Spark调度底层执行原理详解(第35天)

系列文章目录 一、Spark应用程序启动与资源申请 二、DAG&#xff08;有向无环图&#xff09;的构建与划分 三、Task的生成与调度 四、Task的执行与结果返回 五、监控与容错 六、优化策略 文章目录 系列文章目录前言一、Spark应用程序启动与资源申请1. SparkContext的创建2. 资…

TS真的比JS更好吗?

前言 在讨论TypeScript&#xff08;TS&#xff09;是否比JavaScript&#xff08;JS&#xff09;更好时&#xff0c;我们需要明确“更好”这一概念的上下文和衡量标准。TypeScript和JavaScript在多个方面有着明显的区别&#xff0c;但它们并不是简单的“好”与“不好”的关系&a…

接口安全配置

问题点&#xff1a; 有员工在工位在某个接口下链接一个集线器&#xff0c;从而扩展上网接口&#xff0c;这种行为在某些公司是被禁止的&#xff0c;那么网络管理员如何控制呢&#xff1f;可以配置接口安全来限制链接的数量&#xff0c;切被加入安全的mac地址不会老化&#xff…

宜春旅游集散中心展厅OLED透明屏方案设计

一、项目概述 为提升宜春旅游集散中心展厅的现代化展示水平&#xff0c;增强游客的参观体验&#xff0c;我们计划在展厅的核心区域引入OLED透明屏技术。该方案旨在通过高科技的视觉呈现方式&#xff0c;将展品信息以虚拟与现实相结合的方式展现&#xff0c;打造出一个既具科技感…

IDEA 2024 maven 配置

1 查看IDEA默认的maven版本 2 下载对应的maven maven 官网&#xff1a;Maven – Welcome to Apache Maven 找到对应的版本(可以选择更高一点的版本&#xff0c;但是不能差太大&#xff0c;可能会有不兼容的情况 复制下载连接&#xff0c;并打开新标签&#xff0c;只保留链接…