为什么堆排序的时间复杂度是O(N*logN)?

2024-04-24 23:28

本文主要是介绍为什么堆排序的时间复杂度是O(N*logN)?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

前言:

堆排序(以排升序为例)

步骤(用大根堆,倒这排,排升序):

1.先把要排列的数组建立成大根堆

2.堆顶元素(82)和最后一个元素交换(2)

3.无视掉交换后的元素(82),对(2)进行向下调整

翻译成代码

mian方法:

heapSortUp方法:

siftDown方法:

堆排序时间复杂度分析:


前言:

本文章以升序为例进行讲解(实际上两种排列时间复杂度都一样,只是比较方式建立大小堆恰好相反)

文章涉及:

1.向下调整算法

2.建堆的方式及其时间复杂度

3.堆排序步骤和时间复杂度分析

注意:如果1,2点还不了解,建议学习完之后在来学习堆排序,才能明白下边讲的是什么。

这里有小编自己写的链接,详细介绍了堆的创建以及向下/向上调整算法:优先级队列(堆)

堆排序(以排升序为例)

如果是排升序,要建立大根堆,反之亦然。

排降序,建立小堆

为什么?

看完他的原理,就知道了。


以数组array={

4,6, 82, 7, 8, 9, 3, 2

}

为例

步骤(用大根堆,倒这排,排升序):

1.先把要排列的数组建立成大根堆

2.堆顶元素(82)和最后一个元素交换(2)

3.无视掉交换后的元素(82),对(2)进行向下调整

此时又变成了大根堆(无视已经排好的82):

此时的82已经被排号了

其是堆排序的整体思路已经讲完了,接下来就是循环执行2,3点
3和9换位置,然后无视排好的82,9,对3进行向下调整:

在向下调整完之后,又是一个大根堆,我们继续,循环这个逻辑,最终的结果就变成了:

这时,就是一个升序的数组了。

翻译成代码

mian方法:

public class Test {public static void main(String[] args) {int[] arr = new int[]{4,6, 82, 7, 8, 9, 3, 2};//要排的数组BigHeap bigHeap = new BigHeap();//这个是我自己写的大根堆bigHeap.init(arr);//把数组传入对象bigHeap.creatHeap();//先建立起大堆bigHeap.heapSortUp();//进行堆排序}
}

heapSortUp方法:

1.我的堆,底层使用elem的数组实现的!!!!!

2.useSize是堆的容量

3.swap的两个参数都是数组的下标

public int[] heapSortUp() {int endIndex = useSize - 1;//最后一个下标的位置(也就是容量减1)while (endIndex > 0) {//如果等于零,就不用交换了swap(0, endIndex);//顶元素和最后一个元素交换endIndex--;//最后一个下标--,就可以起到无视排号数,的作用siftDown(0, endIndex);}return elem;}

siftDown方法:

public void siftDown(int parent, int end) {//parent end都是有效下标int child = 2 * parent + 1;//默认是左孩子while (child <= end) {//调整到最后一个子节点,为止//先判断是否有右孩子if (child + 1 <= end) {//如果有判断谁大,大的当左孩子if (elem[child] < elem[child + 1]) {child++;}}//左孩子在和父节点进行比较if (elem[child] > elem[parent]) {//如果孩子节点大,那么父子交换位置swap(child, parent);} else {break;//如果父节点已经是最大的就不用调整了,这棵树就是大根堆//因为我们会从后往前,把这棵树(数组)一次遍历调整完}//下面继续往往下面调整parent = child;//当前的父亲,变成自己的孩子child = parent * 2 + 1;//孩子变成孩子的孩子}}

堆排序时间复杂度分析:

其实很简单,上面我们一共说了三个方法:

1.main

2.heapSortUp

3.siftDown

我们从main方法切入,实际上执行堆排序的程序就是这两步:

 public static void main(String[] args) {int[] arr = new int[]{4,6, 82, 7, 8, 9, 3, 2};BigHeap bigHeap = new BigHeap();bigHeap.init(arr);//这两步:bigHeap.creatHeap();//先创建大根堆bigHeap.heapSortUp();//堆排序,内部实现等一下看}

学了堆我们都直到,建堆的时间复杂度是O(N)

然后在加上heapSortUp的时间复杂度,不就是堆排序的时间复杂度了吗?

具体看一下,heapSortUp:

 public int[] heapSortUp() {int endIndex = useSize - 1;while (endIndex > 0) {swap(0, endIndex);endIndex--;siftDown(0, endIndex);}return elem;}

useSize和siftDown是我们要计算的时间复杂度,其他都是常量不用管

useSize实际上就是所给数组的长度嘛,就是N咯

学了siftDown就是向下调整算法,向下调整算法向上调整算法的时间复杂度都是logN(以2为底)-----》至于怎么算的,可以看小编文章前言部分的链接

所以堆排序的时间复杂度==O(useSize)+O(siftDown)*O(creatHeap)=N+N*logN

然后取得最高阶,则时间复杂度就是O(N*logN)

这篇关于为什么堆排序的时间复杂度是O(N*logN)?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/933125

相关文章

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

Python如何获取域名的SSL证书信息和到期时间

《Python如何获取域名的SSL证书信息和到期时间》在当今互联网时代,SSL证书的重要性不言而喻,它不仅为用户提供了安全的连接,还能提高网站的搜索引擎排名,那我们怎么才能通过Python获取域名的S... 目录了解SSL证书的基本概念使用python库来抓取SSL证书信息安装必要的库编写获取SSL证书信息

MySQL 日期时间格式化函数 DATE_FORMAT() 的使用示例详解

《MySQL日期时间格式化函数DATE_FORMAT()的使用示例详解》`DATE_FORMAT()`是MySQL中用于格式化日期时间的函数,本文详细介绍了其语法、格式化字符串的含义以及常见日期... 目录一、DATE_FORMAT()语法二、格式化字符串详解三、常见日期时间格式组合四、业务场景五、总结一、

如何利用Java获取当天的开始和结束时间

《如何利用Java获取当天的开始和结束时间》:本文主要介绍如何使用Java8的LocalDate和LocalDateTime类获取指定日期的开始和结束时间,展示了如何通过这些类进行日期和时间的处... 目录前言1. Java日期时间API概述2. 获取当天的开始和结束时间代码解析运行结果3. 总结前言在J

修改若依框架Token的过期时间问题

《修改若依框架Token的过期时间问题》本文介绍了如何修改若依框架中Token的过期时间,通过修改`application.yml`文件中的配置来实现,默认单位为分钟,希望此经验对大家有所帮助,也欢迎... 目录修改若依框架Token的过期时间修改Token的过期时间关闭Token的过期时js间总结修改若依

Go Mongox轻松实现MongoDB的时间字段自动填充

《GoMongox轻松实现MongoDB的时间字段自动填充》这篇文章主要为大家详细介绍了Go语言如何使用mongox库,在插入和更新数据时自动填充时间字段,从而提升开发效率并减少重复代码,需要的可以... 目录前言时间字段填充规则Mongox 的安装使用 Mongox 进行插入操作使用 Mongox 进行更

对postgresql日期和时间的比较

《对postgresql日期和时间的比较》文章介绍了在数据库中处理日期和时间类型时的一些注意事项,包括如何将字符串转换为日期或时间类型,以及在比较时自动转换的情况,作者建议在使用数据库时,根据具体情况... 目录PostgreSQL日期和时间比较DB里保存到时分秒,需要和年月日比较db里存储date或者ti

Python 标准库time时间的访问和转换问题小结

《Python标准库time时间的访问和转换问题小结》time模块为Python提供了处理时间和日期的多种功能,适用于多种与时间相关的场景,包括获取当前时间、格式化时间、暂停程序执行、计算程序运行时... 目录模块介绍使用场景主要类主要函数 - time()- sleep()- localtime()- g

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2