可以通过siftdown或者siftup建立二叉堆。

  • siftdown: 如果节点小于其最大的子节点,将二者进行交换,直到节点大于或等于所有子节点。整个过程节点向下调整。
  • siftup: 如果节点大于其父节点,将二者交换,直到节点小于或者等于其父节点。整个过程节点向上调整。

siftdown或者siftup在最坏情况下都是O(logn)。siftdown操作次数取决于节点离堆底的距离,siftup的操作次数取决于节点离堆顶的距离。siftdown的效率更高一些,因为建堆时计算每个节点到底部或者顶部的距离,由于大部分节点靠近底部,siftdown的总体操作次数少一些。

通过siftdown建堆

代码

   //swap current value with the largest child.private static void siftdown(int[] arr, int k, int len){while(2 * k + 1 < len){int child = 2 * k + 1;if(2 * k + 2 < len && arr[2 * k + 1] < arr[2 * k + 2]){child = 2 * k + 2;}if(arr[k] >= arr[child]){break;}int temp = arr[k];arr[k] = arr[child];arr[child] = temp;k = child;}}//O(logn)public static void buildheap(int[] arr){for(int i = arr.length - 2; i >= 0; i--){siftdown(arr, i, arr.length);}}

二叉堆中
倒数第一层 (堆底)的节点不需要通过siftdown交换,0次操作 * ( n/2 个节点 )
倒数第二层的节点最多进行1次交换到堆底,1次操作 * n/4个节点
倒数第三层的节点最多进行2次交换到堆底,2次操作 * n/8个节点

第一层的最多进行h (h 是二叉堆的深度)次交换到堆底,h次操作 * 1 个节点

如何确定每一层的节点数?
假设二叉堆的最后一层是满的。二叉树所有节点数和为
1+2+4+...+2h=n2h+1−1=n2h=n+12h=log2(n+1)−11 + 2 + 4 + ... + 2^h = n \\ 2^{h + 1} - 1 = n \\ 2^h = \frac{n + 1}{2} \\ h = log_2(n + 1) - 1 1+2+4+...+2h=n2h+1−1=n2h=2n+1​h=log2​(n+1)−1
x 是二叉堆深度,n是整个节点个数。最后一层的节点数是2h2^h2h 约为n2\frac{n}{2}2n​。根据二叉堆的特性,前面一层的节点数是后一层的12\frac{1}{2}21​。依次得出倒数第二层的节点数是n4\frac{n}{4}4n​,倒数第三层的节点数是n8\frac{n}{8}8n​,等等。

交换次数总共为
sum=0×n2+1×n4+2×n8+...+h×1,h=lognsum = 0 \times \frac{n}{2} + 1 \times \frac{n}{4} + 2 \times \frac{n}{8} + ... + h \times 1, h = logn sum=0×2n​+1×4n​+2×8n​+...+h×1,h=logn

推导方法1:

公式2:每一项都是正数,因此有限的区间求和小于无限区间求和
公式3: 指数求导的公式
公式4: 等比数列求和公式
公式5: 指数求导公式

推导方法2:

综上,采用siftdown建堆的时间复杂度O(n)。

通过siftup建堆

详细代码见

    //swap current value with its parent if parent is less than current valueprivate static void siftup(int[] arr, int k){while(k > 0){int parent = (k - 1) / 2;//terminate when arr satisfies the heap characteristicif(arr[k] <= arr[parent]){break;}//otherwise, swap curr value with its parent, keep siftupint temp = arr[k];arr[k] = arr[parent];arr[parent] = temp;k = parent;}}public static buildheap(int[] arr){for(int i = 1; i < arr.length; i++){siftup(arr, i);}
}

通过siftup建立二叉堆的时间复杂度是O(nlogn)。
二叉堆中,
第一层的节点不需要交换,0次操作 * 1 个节点
第二层的节点最多进行1次交换到堆顶,1次操作 * 2个节点
第三层的节点最多进行2次交换到堆顶,2次操作 * 4个节点

底层的最多进行h (h 是二叉堆的深度)次交换到堆顶,h次操作 * n/2 个节点

交换次数总共为
sum=h×n2+(h−1)×n4+(h−2)×n8+...+0×1,h=lognsum = h \times \frac{n}{2} + (h - 1) \times \frac{n}{4} + (h - 2) \times \frac{n}{8} + ... + 0 \times 1, h = logn sum=h×2n​+(h−1)×4n​+(h−2)×8n​+...+0×1,h=logn

其中,第一项h×n2=logn×n2h \times \frac{n}{2} = logn \times \frac{n}{2}h×2n​=logn×2n​,最好的情况时间复杂度已经是O(nlogn)

两种方法推导建堆的时间复杂度O(n)相关推荐

  1. 建堆的时间复杂度分析

    现在常有两种建堆的方法,而这两种方法又有着不同的时间复杂度.下面分别陈述: (1)自顶向下的建堆方式 这种建堆的方法具有O(n*log2n)的时间复杂度.从根结点开始,然后一个一个的把结点插入堆中.当 ...

  2. windows 搭建kms服务器激活_自建KMS激活服务器的两种方法

    你还在用网上那种坑爹的Ghost盗版系统吗?内置各种辣鸡.流氓软件,新系统?纯净版Ghost系统?不存在的~ 在开始自建KMS服务器之前,我觉得很有必要给大家分享一个神站,没错就是MSDN! 地址:h ...

  3. selenium webdriver 使用webDriver点击ENTER建的两种方法

    使用webDriver点击ENTER建的两种方法:. First: driver.findElement(By.id("idValue")).sendKeys(Keys.ENTER ...

  4. 百钱买百鸡python编程列表推导式_使用循环和列表推导式两种方法求解百钱买百鸡问题。假设大鸡5元一只,中鸡3元一只,小鸡1元三只,现有100元钱想买100只鸡,有多少种买法?...

    [程序题]编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数 1/1+1/3+...+1/n [单选题]患者男,67岁.确诊为原发性支气管肺癌,为行手术 ...

  5. php 带建数组转字符串,php数组转换为字符串的两种方法详解【附视频】

    本篇文章主要给大家介绍PHP数组转换为字符串的两种方法.(文章末尾附有对应的视频教程) 第一种方法:使用PHP本身的函数implode来直接将数组转换为字符串. 第二种方法:使用循环遍历数组元素拼接成 ...

  6. Java中的string定义的两种方法和区别

    java中的String定义的两种方法和区别 第一种:new方式 String s1 = new String("hello world"); String s2 = new St ...

  7. sqrt函数模拟实现的两种方法

    起因:在leetcode刷题时,有一道题目考察了有关sqrt的原理的题目,当时就去查了网上的文章,结果发现,一开始的时候看的很懵,最后也是搞定了两种方法,今天我就以最简单的方式写下这两种方式的思路讲解 ...

  8. 建堆的时间复杂度详解

    接上之前堆的博客,里面我曾提过建堆的时间复杂度是O(N),那么是为什么呢?下面进行推导 按照最坏情况,该堆是满二叉树,如上图 又依据公式: 黑色框圈住的代表的是每层有的节点的个数 第一层有2^(1-1 ...

  9. cpp 怎么连接mysql_C++连接mysql数据库的两种方法

    现在正做一个接口,通过不同的连接字符串操作不同的数据库.要用到mysql数据库,以前没用过这个数据库,用access和sql server比较多.通过网上的一些资料和自己的摸索,大致清楚了C++连接m ...

最新文章

  1. nginx限制ip,只允许域名访问
  2. 数据中心液冷技术发展分析
  3. Spring Security + WebSocket——@MessageMapping中Authentication为NULL解决方案之一
  4. 2013年7月28日web前端学习笔记-------head相关标签应用
  5. 金山吹响讨伐灰鸽子的号角
  6. arduino灯光装置_【pinpong库控制硬件】之Arduino uno-调光台灯
  7. MySQL--pymysql模块
  8. Windows Mobile下猜数字游戏的TDD实现
  9. POI数据获取-Python
  10. axure 抖音部件库_抖音常用工具和素材库大全
  11. 亲戚关系关系算法java程序_python版亲戚关系计算器
  12. 微信小程序--石头剪刀布(小游戏)
  13. xlsx怎么设置行高列宽_Excel2016中调整行高和列宽的两种方法
  14. 3D打印机的调平问题
  15. 超详细Redis入门教程——Redis概述
  16. 微信固定金额收款码批量生成
  17. 论文翻译:2020_RNNoise:A Hybrid DSP/Deep Learning Approach to Real-Time Full-Band Speech Enhancement...
  18. 记账本记录日常收支 如何查看某个时间段的明细
  19. wireshark 手机抓包_美团外卖抓包分析
  20. AP Autosar平台设计 9 诊断

热门文章

  1. 关于机器人方面的sci论文_工程-机器人SCI期刊推荐
  2. WHmcs中的插件开发
  3. photoshop6下载与安装
  4. SEO当中能事半功倍的选择——外贸建站域名如何选
  5. Harry Potter and the Prisoner of Azkaban
  6. 工业互联网进入发展快车道,先上车的企业现在如何?
  7. 教大家搭建一个手机app软件导航网
  8. Syzmlw让子弹飞下载地址
  9. xp桌面显示计算机,xp系统电脑开机后不显示桌面
  10. 【LeetCode】【前K个高频单词】