建堆的时间复杂度和堆排序

文章目录

  • 建堆的时间复杂度
    • 向下调整建堆
    • 向上调整建堆
  • 堆排序
    • 实现

建堆的时间复杂度

下面都以建大堆演示

向下调整建堆

void Adjustdown(HPDataType* a, int size,int parent)
{int child = parent * 2 + 1;while (child < size){if (child+1<size&&a[child + 1] >a[child]){child++;}if (a[parent] <a[child]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}

在这里插入图片描述
我们根据求堆的节点总数(利用等比数列求和公式)可以知道堆节点总数N和堆高度h之间的关系:N=2^h-1。再根据图片规律求出移动节点的步数:
在这里插入图片描述

因此,利用向下调整建堆的的时间复杂度为O(N)。

向上调整建堆

void Adjustup(HPDataType*a,int child)
{int parent = (child - 1) / 2;while (child > 0){if (a[parent] < a[child]){Swap(&a[parent], &a[child]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

在这里插入图片描述

对比两种建堆的时间复杂度我们能看出向下调整建堆要优于向上调整建堆,接下来我们利用向下调整建堆实现堆排序。

堆排序

排序可以分为升序排序和降序排序,实现堆排序前,我们先要思考,升序和降序哪种适合大堆,哪种适合小堆?假如我们现在要实现升序排序,我们可以先用小堆理一遍思路,小堆结构是堆顶元素最小,如果我们直接把堆顶拿出来,那么下面父子兄弟节点的关系全乱了,最差的情况需要把每个节点都向上调整一遍,时间复杂度太高。如果选择大堆,我们只需把每次堆顶的元素和堆中最后一个元素交换,然后让新的堆顶向下调整,(每次交换完后最后的元素不参与后续的向下调整)就能得到一个升序的数组。

void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}void Heapsort(int *a,int n)
{for (int i = 1; i < n; i++){Adjustup(a, i);}int end = n - 1;while (end>0){Swap(&a[0], &a[end]);Adjustdown(a, end, 0);--end;}
}

先建一个大堆,然后不断将堆顶和堆尾元素交换,再让新堆顶向下调整得到次大的数

实现

int main()
{int a[] = { 4,6,8,2,3,7,1,5 };Heapsort(a, sizeof(a) / sizeof(int));for (int i = 0; i < sizeof(a) / sizeof(int); i++){printf("%d ", a[i]);}printf("\n");return 0;
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

树莓派 SPI操作

一、 开启树莓派spi功能 1sudo raspi-config 选择 Advanced Options -> SPI -> yes 启动SPI内核驱动 运行lsmod命令&#xff0c;可以看到spi模块已启动 在/dev路径下面&#xff0c;我们可以发现两个spi设备 spi管脚如下如所有&#xff0c;左边方框的管脚分别为MOS…

旋转框(obb)目标检测计算iou的方法

首先先定义一组多边形&#xff0c;这里的数据来自前后帧的检测结果 pre [[[860.0, 374.0], [823.38, 435.23], [716.38, 371.23], [753.0, 310.0]],[[829.0, 465.0], [826.22, 544.01], [684.0, 539.0], [686.78, 459.99]],[[885.72, 574.95], [891.0, 648.0], [725.0, 660.0]…

RocketMQ-RocketMQ快速实战及集群原理

一、MQ简介 ​ MQ&#xff1a;MessageQueue&#xff0c;消息队列。是在互联网中使用非常广泛的一系列服务中间件。 这个词可以分两个部分来看&#xff0c;一是Message&#xff1a;消息。消息是在不同进程之间传递的数据。这些进程可以部署在同一台机器上&#xff0c;也可以分布…

python动态加载内容抓取问题的解决实例

问题背景 在网页抓取过程中&#xff0c;动态加载的内容通常无法通过传统的爬虫工具直接获取&#xff0c;这给爬虫程序的编写带来了一定的技术挑战。腾讯新闻&#xff08;https://news.qq.com/&#xff09;作为一个典型的动态网页&#xff0c;展现了这一挑战。 问题分析 动态…

LeetCode刷题---打家劫舍问题

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、打家劫舍 题目链接&#xff1a;打家劫舍 题目描述 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定…

CTO对生活和工作一点感悟

陌生人&#xff0c;你好啊。 感谢CSDN平台让我们有了隔空认识&#xff0c;交流的机会。 我是谁&#xff1f; 我呢&#xff0c;毕业快11年&#xff0c;在网易做了几年云计算&#xff0c;后来追风赶上了大数据的浪潮&#xff0c;再到后来混迹在AI、智能推荐等领域。 因为有一颗…

Discuz论坛自动采集发布软件

随着网络时代的不断发展&#xff0c;Discuz论坛作为一个具有广泛用户基础的开源论坛系统&#xff0c;其采集全网文章的技术也日益受到关注。在这篇文章中&#xff0c;我们将专心分享通过输入关键词实现Discuz论坛的全网文章采集&#xff0c;同时探讨采集过程中伪原创的发布方法…

菜鸟学习日记(Python)——基本数据类型

Python 中的变量不需要声明。每个变量在使用前都必须赋值&#xff0c;变量赋值以后该变量才会被创建。 在 Python 中&#xff0c;变量就是变量&#xff0c;它没有类型&#xff0c;我们所说的"类型"是变量所指的内存中对象的类型。 等号&#xff08;&#xff09;用来…

计算机网络:应用层(下篇)

文章目录 前言一 、电子邮件&#xff08;Email&#xff09;1.邮件服务器2.SMTP[RFC 2821]3.邮件报文格式4.邮件访问协议 二、DNS&#xff08;域名系统&#xff09;1.DNS的历史2.DNS总体思路和目标&#xff08;1&#xff09;问题1&#xff1a;DNS名字空间&#xff08;2&#xff…

nodejs+vue+elementui+express青少年编程课程在线考试系统

针对传统线下考试存在的老师阅卷工作量较大&#xff0c;统计成绩数据时间长等问题&#xff0c;实现一套高效、灵活、功能强大的管理系统是非常必要的。该系统可以迅速完成随机组卷&#xff0c;及时阅卷、统计考试成绩排名的效果。该考试系统要求&#xff1a;该系统将采用B/S结构…

Java全栈基础篇--集合

集合 集合&#xff1a;集合是java中提供的一种容器&#xff0c;可以用来存储多个数据。 特点&#xff1a; 长度不固定&#xff0c;还可以存储不同的数据&#xff08;但是一般都用同一类型&#xff09; 集合和数组既然都是容器&#xff0c;它们有啥区别呢&#xff1f; 数组的长…

在Spring Boot中使用JavaMailSender发送邮件

用了这么久的Spring Boot&#xff0c;我们对Spring Boot的了解应该也逐步进入正轨了&#xff0c;这篇文章讲的案例也在我们的实际开发中算是比较实用的了&#xff0c;毕竟我们完成注册功能和对用户群发消息&#xff0c;都可以采用到邮箱发送功能&#xff0c;往下看&#xff0c;…