两种方法推导建堆的时间复杂度O(n)
可以通过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+1h=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)自顶向下的建堆方式 这种建堆的方法具有O(n*log2n)的时间复杂度.从根结点开始,然后一个一个的把结点插入堆中.当 ...
- windows 搭建kms服务器激活_自建KMS激活服务器的两种方法
你还在用网上那种坑爹的Ghost盗版系统吗?内置各种辣鸡.流氓软件,新系统?纯净版Ghost系统?不存在的~ 在开始自建KMS服务器之前,我觉得很有必要给大家分享一个神站,没错就是MSDN! 地址:h ...
- selenium webdriver 使用webDriver点击ENTER建的两种方法
使用webDriver点击ENTER建的两种方法:. First: driver.findElement(By.id("idValue")).sendKeys(Keys.ENTER ...
- 百钱买百鸡python编程列表推导式_使用循环和列表推导式两种方法求解百钱买百鸡问题。假设大鸡5元一只,中鸡3元一只,小鸡1元三只,现有100元钱想买100只鸡,有多少种买法?...
[程序题]编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数 1/1+1/3+...+1/n [单选题]患者男,67岁.确诊为原发性支气管肺癌,为行手术 ...
- php 带建数组转字符串,php数组转换为字符串的两种方法详解【附视频】
本篇文章主要给大家介绍PHP数组转换为字符串的两种方法.(文章末尾附有对应的视频教程) 第一种方法:使用PHP本身的函数implode来直接将数组转换为字符串. 第二种方法:使用循环遍历数组元素拼接成 ...
- Java中的string定义的两种方法和区别
java中的String定义的两种方法和区别 第一种:new方式 String s1 = new String("hello world"); String s2 = new St ...
- sqrt函数模拟实现的两种方法
起因:在leetcode刷题时,有一道题目考察了有关sqrt的原理的题目,当时就去查了网上的文章,结果发现,一开始的时候看的很懵,最后也是搞定了两种方法,今天我就以最简单的方式写下这两种方式的思路讲解 ...
- 建堆的时间复杂度详解
接上之前堆的博客,里面我曾提过建堆的时间复杂度是O(N),那么是为什么呢?下面进行推导 按照最坏情况,该堆是满二叉树,如上图 又依据公式: 黑色框圈住的代表的是每层有的节点的个数 第一层有2^(1-1 ...
- cpp 怎么连接mysql_C++连接mysql数据库的两种方法
现在正做一个接口,通过不同的连接字符串操作不同的数据库.要用到mysql数据库,以前没用过这个数据库,用access和sql server比较多.通过网上的一些资料和自己的摸索,大致清楚了C++连接m ...
最新文章
- nginx限制ip,只允许域名访问
- 数据中心液冷技术发展分析
- Spring Security + WebSocket——@MessageMapping中Authentication为NULL解决方案之一
- 2013年7月28日web前端学习笔记-------head相关标签应用
- 金山吹响讨伐灰鸽子的号角
- arduino灯光装置_【pinpong库控制硬件】之Arduino uno-调光台灯
- MySQL--pymysql模块
- Windows Mobile下猜数字游戏的TDD实现
- POI数据获取-Python
- axure 抖音部件库_抖音常用工具和素材库大全
- 亲戚关系关系算法java程序_python版亲戚关系计算器
- 微信小程序--石头剪刀布(小游戏)
- xlsx怎么设置行高列宽_Excel2016中调整行高和列宽的两种方法
- 3D打印机的调平问题
- 超详细Redis入门教程——Redis概述
- 微信固定金额收款码批量生成
- 论文翻译:2020_RNNoise:A Hybrid DSP/Deep Learning Approach to Real-Time Full-Band Speech Enhancement...
- 记账本记录日常收支 如何查看某个时间段的明细
- wireshark 手机抓包_美团外卖抓包分析
- AP Autosar平台设计 9 诊断