首页 > 其他分享 >线性时间构造最大堆

线性时间构造最大堆

时间:2024-04-17 20:55:57浏览次数:13  
标签:最大 max 构造 heapify 二叉树 largest 线性 2n 节点

堆:是一个数组,近似的完全二叉树,除了最底层外,该树是完全充满的.

最小堆:A[i] <= A[2i] && A[i] <= A[2i+1]

最大堆:A[i] >= A[2i] && A[i] >= A[2i+1]

下标从1开始算起

维护堆

max_heapify(A, i):维护最大堆的性质,让A[i]的值逐级下降

    if 2*i <= len(A) and A[2*i] > A[i]:
        largest = 2*i
    else:
        largest = i
    if 2*i+1 <= len(A) and A[2*i+1] > A[i]:
        largest = 2*i+1
    else:
        largest = i
    if largest != i:
        A[i],A[largest] = A[largest],A[i]
        max_heapify(A,largest)

时间复杂度:(见算法导论第三版6.2节)

对于一个以i为根节点、大小为n的子树,交换值的代价为O(1),加上,以i的一个孩子为根节点的子树运行max_heapify的时间,每个孩子的子树的大小至多为2n/3(最坏情况发生在树的最底层恰好半满的时候)

这儿的2n/3的推导:

1、假设有一个包含n个元素的堆, 计算高度为 h=k 的节点数的上限
2、假设有一个完全二叉树,其中底层正好半满,即有x个节点。我们可以通过添加x个节点来构造一个满二叉树
3、满二叉树的大小为 **n + x = 2x * 2 - 1 = 4x - 1**。因此,我们有 **n = 3x - 1**,进而 **x = (n + 1) / 3**。
4、在满二叉树中,第i层的节点数目为 **(满树大小 - 1) / 2**。代入上述结果,我们得到 **2x - 1 = 2n/3 - 1/3 < 2n / 3**。
因此,在一个最大堆中,节点i的子树大小至多为2n/3

由此,

T(n) ≤ T(2n/3) + O(1) ---->  T(n)=O(lg n)

即对于一个树高为h的节点,该操作的时间复杂度是O(h)。

建堆

最大堆:自底向上
build-max-heap(A):从最后一个非叶子节点开始,逐级向上维护最大堆的性质

A.heap-size = len(A)
for i in range(len(A)//2,0,-1):
    max_heapify(A,i)

时间复杂度
初看是O(n lgn),精确是:O(n)

1、高为h的 至多节点个数
6.3-3
2、线性时间构造最大堆
时间
这儿推导不是很明白!!!再看!!!

堆排序

heapsort(A):

build-max-heap(A)
for i in range(len(A),1,-1):
    A[1],A[i] = A[i],A[1]
    A.heap-size = A.heap-size - 1
    max_heapify(A,1)

标签:最大,max,构造,heapify,二叉树,largest,线性,2n,节点
From: https://www.cnblogs.com/xuan01/p/18141766

相关文章

  • 数据分享|R语言用lme4多层次(混合效应)广义线性模型(GLM),逻辑回归分析教育留级调查数据|附
    全文链接:http://tecdat.cn/?p=22813最近我们被客户要求撰写关于混合效应的研究报告,包括一些图形和统计输出。本教程为读者提供了使用频率学派的广义线性模型(GLM)的基本介绍。具体来说,本教程重点介绍逻辑回归在二元结果和计数/比例结果情况下的使用,以及模型评估的方法本教程使用......
  • [学习笔记] 高斯消元 - 线性代数
    高斯-约旦消元下面给两道板子【模板】高斯消元法最最基础的板子,没啥哆嗦的。下面给出高斯-约旦消元解法。#include<bits/stdc++.h>usingnamespacestd;intn,dt=1;doubleeps=1e-9,m[102][102];intmain(){ scanf("%d",&n); for(inti=1;i<=n;++i) for(intj......
  • 深度解读《深度探索C++对象模型》之拷贝构造函数
    接下来我将持续更新“深度解读《深度探索C++对象模型》”系列,敬请期待,欢迎关注!也可以关注公众号:iShare爱分享,自动获得推文。写作不易,请有心人到我的公众号上点点赞支持一下,增加一下热度,也好让更多的人能看到,公众号里有完整的文章列表可供阅读。有以下三种情况,一个类对象的初始......
  • 《线性代数的本质》笔记(09)
    09-基变换基向量不同,则相同坐标的向量实际上并不是同一个。将新的基向量看作是线性变换,则其列应该是原本的基向量现在的位置。将一个新坐标系下的向量a(x,y)转换到我们的坐标系中:用这个矩阵乘以这个向量。原因:用两组基向量分别表示向量在两个坐标系下的位置,则结果应该是相同的。所......
  • springboot简单正确的使用构造函数注入
    一个一个写构造函数太麻烦了,而且代码会显得非常多,这里我们可以采用lombok快捷注入但是我们并不是所有的成员变量都需要进行注入,所以使用@RequiredArgsConstrucotr需要构造函数的部分添加上final关键字"Alwaysuseconstructorbaseddependencyinjectioninyourbeans.Alwa......
  • 为什么python的数据库语句要用参数化构造的方式
    以下是一个python的数据库插入语句self.cur.execute('''INSERTINTObooks(url,title,product_type,price_excl_tax,price_incl_tax,availability,num_reviews,rating,category,describe)VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)&......
  • 节省时间和资源:了解如何最大化渲染农场的排队管理效率
    ​在3D渲染领域,时间的价值无可替代。随著3D艺术家与制作工作室不断挑战技术极限,对高效计算资源的渴求空前增长,渲染农场因此成为了渲染任务中不可或缺的力量。其核心在于排队系统——这一动态且复杂的结构负责安排和最优化渲染任务的执行顺序与时间,确保了渲染效率和资源的充分利用......
  • 深度解读《深度探索C++对象模型》之默认构造函数
    接下来我将持续更新“深度解读《深度探索C++对象模型》”系列,敬请期待,欢迎关注!也可以关注公众号:iShare爱分享,主动获得推文。提到默认构造函数,很多文章和书籍里提到:“在需要的时候编译器会自动生成一个默认构造函数”。那么关键的问题来了,到底是什么时候需要?是谁需要?比如下面的......
  • 初等双射构造
    MyBlogs下文中\([n]\)表示\(\{1,2,3\dotsn\}\)。P0对于正整数\(n\),称\(a_{1\dotsk}\)是\(n\)的有序划分,当且仅当\(\sum_ia_i=n\)。给定\(n(\geq2)\),求满足\(\sum_{i}[2|a_i]\)是偶数的有序划分个数。答案:\(2^{n-2}\)。\(n\)的所有划分可以看成有\(n-1\)......
  • 《线性代数的本质》(06-附注2-07)
    06-逆矩阵、列空间、秩与零空间线性方程组:A\(\vec{x}\)=\(\vec{v}\)线性代数的一个作用:帮助我们处理线性方程组。形式:矩阵与向量的乘法。几何意义:寻找一个向量\(\vec{x}\),这个向量在特定的线性变换之后与目标向量\(\vec{v}\)重合。行列式不等于0:有且仅有一个向量再变......