堆排序+TOPK问题

news2024/10/6 12:22:25

文章目录

  • 一.堆排序
    • 1.使用向上还是向下调整建堆好?
      • (1)向上调整算法建堆的时间复杂度
        • 1. 完整过程
      • (2)向下调整算法建堆的时间复杂度
        • 1.完整过程
      • (3)总结
    • 2. 排升序
      • (1) 建小堆
      • (2) 建大堆
    • 3. 堆排序时间复杂度统计
    • 4.完整代码
  • 二 、 TOPK问题
    • 1. 概念
    • 2.两种方法
      • 第一种
        • 缺陷
      • 第二种
        • 思想
        • 过程
    • 3.完整代码

一.堆排序

1.使用向上还是向下调整建堆好?

(1)向上调整算法建堆的时间复杂度

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;
		}
	}
}

1. 完整过程

在这里插入图片描述

由于第一层不需要调整,所以从第二层开始 这里没有详细算,因为我们发现在最后的2^(h-1)*(h-1) 用公式拆分后,就可以算出结果
通过大O的渐进表示法, 时间复杂度为O(N * logN)

(2)向下调整算法建堆的时间复杂度

void adjustdown(HPDatatype* a, int parent,int size)//向下调整算法
{
	int child = parent * 2 + 1;//假设为左孩子
	while (child<size)
	{
		if (child+1<size&&a[child] < a[child + 1])//如果假设不成立,就为右孩子
		{
			child++;
		}
		if (a[parent] < a[child])//孩子大于父亲
		{
			swap(&a[parent], &a[child]);
			parent = child;
			child=parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

1.完整过程

在这里插入图片描述

  • 由于2^h-1为二叉树总节点个数,所以最后一层为h-1, 但因向下调整算法是从倒数第二层的父节点开始的即 从h-2层开始
  • 这里不太懂为什么从倒数第二层的父亲节点开始 可以看:堆的带图详解

在这里插入图片描述

  • 由于大O的渐进表示法,可以把时间复杂度看作为O(N)

(3)总结

  • 因为 向上调整算法的时间复杂度为O(NlogN) ,而向下调整算法的时间复杂度为 O(N)
  • 所以使用向下调整算法建堆更好

2. 排升序

(1) 建小堆

在这里插入图片描述

  • 假设小堆如图所示

在这里插入图片描述

  • 只能取到最小的节点,再次想要取次小的节点时会打乱节点之间的结构,从而需要重新建堆

  • 而重新建堆的时间复杂度为O(N),遍历一次数组的时间复杂度也为O(N),没有效率

(2) 建大堆

在这里插入图片描述

  • 假设为大堆所图所示
    在这里插入图片描述

交换最大的节点与最后一个节点,此时左子树与右子树结构没有发生变化 当从最后一个节点到第二层完成交换时,
共操作了 2^h 次 ,N=2^h ,h=log N
即时间复杂度为O(logN)

3. 堆排序时间复杂度统计

在整体过程中,主要有 向下调整算法建堆排序组成
向下调整算法建堆的时间复杂度为O(N)
排序的时间复杂度为O(logN)
堆排序的时间复杂度为O(NlogN)

4.完整代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void swap(int * s1, int * s2)
{
int tmp = 0;
tmp = *s1;
*s1 = *s2;
*s2 = tmp;
}
void adjustdown(int * a, int parent, int size)//向下调整算法
{
int child = parent * 2 + 1;//假设为左孩子
while (child < size)
{
if (child + 1 < size && a[child] < a[child + 1])//如果假设不成立,就为右孩子
{
child++;
}
if (a[parent] < a[child])//孩子大于父亲
{
swap(&a[parent], &a[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void print(int* a, int n)
{
int i = 0;
for (i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
}
void heapsort(int* a, int n)//堆排序——升序
{
int i = 0;
for (i = (n - 1 - 1) / 2; i >= 0; i--)//使用向下调整算法 时间复杂度为O(N)
{
adjustdown(a, i, n);
}

int end = n - 1;//排升序,建大堆 时间复杂度为O(logN)
while (end > 0)//end作为下标当为0时,说明只剩下一个数,不需要调整
{
swap(&a[0], &a[end]);//交换最大的数与最后一个数的位置,并将前n-1个数再次向下调整
adjustdown(a, 0, end);//此时end作为整体调整的个数
end--;
}
}
int main()
{
int arr[] = { 27,15,19,18,28,34,65,49,25,37 };
int n = sizeof(arr) / sizeof(arr[0]);
heapsort(arr, n);
print(arr, n);

return 0;
}

二 、 TOPK问题

1. 概念

即求数据结合中前k个最大的元素或者最小的元素,一般情况下数据量比较大

2.两种方法

第一种

建立一个N个数的大堆,删除k次,依次取堆顶
这种方法我们在上一篇实现过,若想看点击:堆的带图详解

缺陷

假设N很大,k很小,比如N=100亿 k=10
1G=1024 * 1024 * 1024Byte 约等于 10亿Byte
100 亿个整数 则需要 40G空间,
正常来说我们把数据放入内存中,再用堆去实现,但若数据太大,内存存不下,直接在磁盘文件中,就不会能在建堆了
40G属于数据太大的情况,所以不能进入内存中

第二种

思想

建立k个数小堆,依次遍历数据,比堆顶的数据大,就进行交换,再向下调整,最后最大的k个数就在小堆中

过程

在这里插入图片描述

假设共有如上的数据,n =6 ,k=3

在这里插入图片描述

  • 取前k个数据建立一个小堆

在这里插入图片描述

再取剩余的数据依次与其比较,若比堆顶数据大,则赋值,同时进行向下调整,使堆顶为最小的数

3.完整代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void swap(int* s1, int* s2)
{
int tmp = 0;
tmp = *s1;
*s1 = *s2;
*s2 = tmp;
}
void adjustdown(int* a, int parent, int size)//向下调整算法 这里以小堆为例
{
int child = parent * 2 + 1;//假设为左孩子
while (child < size)
{
if (child + 1 < size && a[child] > a[child + 1])//如果假设不成立,就为右孩子
{
child++;
}
if (a[parent] > a[child])//孩子小于父亲  
{
swap(&a[parent], &a[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
int main()
{
int n = 0;
int k = 0;
printf("请输入数字:>");
scanf("%d%d", &n, &k);
FILE* pf = fopen("qwe.txt", "w");
if (pf == NULL)
{
perror("fopen tail");
exit(-1);
}
int i = 0;
srand(time(0));
for (i = 0; i < n; i++)//将n个数据传入文件中
{
int ret = rand();
fprintf(pf, "%d\n", ret);
}
fclose(pf);//输入文件数据后就关闭
//
FILE* cout = fopen("qwe.txt", "r");
if (cout == NULL)
{
perror("fopen tail");
exit(-1);
}
int* minheap = (int*)malloc(sizeof(int) * k);
if (minheap == NULL)
{
perror(" malloc fail");
}

for (i = 0; i < k; i++)//将k个数据传入数组中 即使用k个数建堆
{
fscanf(cout, "%d", &minheap[i]);
}

for (i = (k - 1 - 1) / 2; i >= 0; i--)//使用向下调算法建小堆
{
adjustdown(minheap, i, k);
}

int val = 0;
while (fscanf(cout, "%d", &val)!=EOF)//将文件剩余的数据继续传入数组中比较
{
if (val > minheap[0])//如果val值比堆顶数据大
{
minheap[0] = val;
adjustdown(minheap, 0, k);//向下调整再次找到最小的堆顶
}
}



for (i = 0; i < k; i++)
{
printf("%d ", minheap[i]);
}
fclose(cout);
cout = NULL;
return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【论文阅读】(2017)The late acceptance Hill-Climbing heuristic

文章目录一、摘要二、Late Acceptance Hill Climbing三、LAHC技术性能的研究3.1 Benchmark problems3.2 Experimental software3.3 Experiments四、LAHC性能评估4.1 评估方法4.2 LAHC不同变体的性能4.3 LAHC与其他技术的比较4.4 LAHC的规模独立性五、Conclusions and future wo…

Salesforce架构师常见问题(上)

Salesforce架构师需要花费大量时间来绘制、讨论、建立和设计稳健的端到端解决方案。架构师角色不仅仅是处理解决方案这么简单&#xff0c;还需要在企业级组织中与多个业务部门打交道。 因此&#xff0c;Salesforce架构师面试需要从以下3个方面准备&#xff1a; Part.1 分享工…

快速理解 JVM 内存模型 对象组成 对象内存分配

快速理解 JVM 内存模型 & 对象组成 & 对象内存分配 JVM 内存模型 JVM 内存模型分为首先在线程纬度可以分为两部分 一部分是 线程共享&#xff1a; 堆、元空间 堆 &#xff1a; 大多数 new 的对象都存在于堆内&#xff0c;也是 GC 主要回收的空间&#xff0c;占据 J…

涨薪跳槽利器,清华大咖总结的 Java 核心突击讲,一应俱全

前言 今天在这里分享一位读者粉丝的经历&#xff1a; 本人双非本科&#xff0c;没拿什么过奖&#xff0c;现在毕业也有三年时间了&#xff0c;大四感觉能力有点不足&#xff0c;进了一家小型的互联网公司实习&#xff1b;期间报名了个线上培训课程&#xff0c;一直在持续学习…

超详细Docker部署SpringBoot+Vue项目(三更博客项目部署)

文章目录1.项目部署规划2.前置工作2.1修改后端配置文件ip2.2修改前端Vue项目运行端口2.3修改前端对应的服务器ip2.4后端项目打包2.4.1解决打包问题2.4.2项目打包&#xff0c;本地运行jar包测试2.5前端项目打包2.6开放端口2.7配置安全组规则3.Docker安装4.拉取镜像5.编写Dockerf…

挂耳式蓝牙耳机哪家的好用,推荐几款实用的挂耳式耳机

时代在进步&#xff0c;而我们也顺势享受着进步过程中所产生的物件&#xff0c;就如骨传导和传统耳机&#xff0c;年轻人更多时候会偏向于骨传导耳机&#xff0c;毕竟骨传导的最大的特点就是佩戴舒适的同时&#xff0c;开放式耳道的设计能够更好的让中耳炎说拜拜。但近期市面上…

Hi,运维,你懂Java吗-No.3:java系统的启动

作为运维&#xff0c;你不一定要会写Java代码&#xff0c;但是一定要懂Java在生产跑起来之后的各种机制。 本文为《Hi&#xff0c;运维&#xff0c;你懂Java吗》系列文章 第三篇&#xff0c;敬请关注后续系列文章 欢迎关注 龙叔运维&#xff08;公众号&#xff09; 持续分享运…

浅谈一下:Java学习中不得不知道的:static (静态)成员

下面笔者&#xff0c;按照之前的Student进行简单的说明&#xff1a; class Student {private String name ;private int age ;private String classRoom ;//上课教室public Student(String name, int age) {this.name name;this.age age;}public void doClass() {System.out…

五、 通信协议

协议&#xff1a;约定&#xff0c;就好比我们来自不同的地方&#xff0c;如果都用各自的家乡话&#xff0c;那么肯定无法沟通&#xff0c;这时我们规定双方都说普通话&#xff0c;这样就可以沟通了&#xff0c;而这个规定就是“协议” 网络通信协议&#xff1a;速率、传输码率…

SpringCloud - 服务注册中心

文章目录1.服务注册中心2.Eureak服务注册中心2.1 Eureka服务注册与发现2.1.1 单机Eurake构建步骤(1) 创建EurekaServer服务注册中心(2) EurekaClient服务注册2.1.2 Eureka集群构建步骤(1) 创建第多个EureakServer注册中心(2) 修改host(模拟)(3) 修改YML配置2.1.3 集群配置Eurek…

搞定企业视频直播:硬件设备、直播网络环境和设备连接说明

阿酷TONY / 2022-11-22 / 原创 / 长沙 / 1.直播硬件设备 电脑硬件推荐配置&#xff1a; 系统&#xff1a;win7系统以上&#xff0c;macOS 10.13.6以上 显卡&#xff1a;独立2G显卡或以上 CPU&#xff1a;i5或以上 内存&#xff1a;4G或以上 选配硬件&#xff1a; …

我有 7种 实现web实时消息推送的方案,7种!

技术交流&#xff0c;公众号&#xff1a;程序员小富 大家好&#xff0c;我是小富&#xff5e; 我有一个朋友&#xff5e; 做了一个小破站&#xff0c;现在要实现一个站内信web消息推送的功能&#xff0c;对&#xff0c;就是下图这个小红点&#xff0c;一个很常用的功能。 不过…

打印机不能正常打印怎么办

第一种&#xff1a;更换驱动&#xff0c;在官网上下载相应的驱动而后安装 第一步&#xff1a;添加打印机和扫描仪 第二步&#xff1a;点击——>我需要的打印机不在列表中 第三步;①如果是USB连接则选择添加本地打印机 ②如果是网络打印机&#xff0c;则选择使用TCP/IP添加…

kubernetes 安装与部署

kubernetes 安装与部署 环境almalinux,centos,rockylinux,redhat的9.1版本使用containerd容器运行时kubernetes v1.25.4root用户 1.设置主机名 2.禁用防火墙 3.禁用selinux 4.禁用swap 5.同步时间 5.桥接流量 6.安装nerdctl-full 7.确认cgroup驱动默认为systemd 8.安装kubead…

Intel MediaSDK sample_decode 官方GPU解码流程学习(一) - DirectX11 D3D11和Vulkan共享资源

很久以前研究过 用NV_DX_interop扩展让D3D和OpenGL共享资源 &#xff0c; OpenGL在当初设计的时候电脑和操作系统还是个相对比较简单的东西&#xff0c;因此OpenGL API设计没有考虑到现在计算机架构的一些特性&#xff0c;比如多核编程和多显卡并发。最近几年出来个Vulkan来接O…

Androguard Documentation:官方文档阅读笔记

打算快速阅读下官方文档&#xff0c;然后做一个笔记方便查阅&#xff0c;文章目录按照官方文档目录来的 DOCUMENTATION Getting Started 使用 androguard axml和androguard arsc解码分析AndroidManifest.xml或者resources.arsc。 创建call graphs可以使用androguard cg&…

快消品b2b电子商务网站建设方案

互联网在改造电商行业商业运作模式和提升运营效率作用方面功不可没&#xff0c;目前B2B电商发展正处在交易上升期特别是B2B快消品电商&#xff0c;这个以万亿为单位的流通规模市场必将掀起巨大的社会价值和运营效率。当然在讨论快消品流通B2B电商行业之前&#xff0c;我们先简单…

C++语言的return语句的一点说明

C语言的return语句的一点说明 为了完成某一功能的程序指令&#xff08;语句&#xff09;的集合&#xff0c;称为函数。在程序中&#xff0c;编写函数的主要目的是将一个需要很多行代码的复杂问题分解为一系列简单的任务来解决&#xff0c;而且&#xff0c;同一个任务&#xff0…

程序员副业之无货源闲鱼

我将从以下这些方面来介绍闲鱼副业。 1. 闲鱼平台能不能挣钱? 2. 闲鱼平台都有哪几种挣钱方式&#xff1f; 3. 小白在闲鱼上怎么挣钱&#xff1f; 4. 能挣多少&#xff1f; 5. 如何养号&#xff1f; 6. 得到高权重的账号闲鱼上架该选什么商品&#xff1f; 7. 卖…

城市消费券,拒绝恶意爬取

作为提振经济的重要把手&#xff0c;城市消费券的作用不言而喻。公开数据显示&#xff0c;2022 年全国各地公布的消费券累计超 100 万亿&#xff0c;在撬动各地消费的过程中起到了举足轻重的作用。 然而&#xff0c;仔细分析各地的核销率就会发现&#xff0c;有很大一部分消费…