【数据结构】堆(二)——堆排序、TOP-K问题

news/2024/5/8 6:10:00/文章来源:https://blog.csdn.net/m0_69061857/article/details/128359186

作者:一个喜欢猫咪的的程序员 

专栏:《数据结构》

喜欢的话:世间因为少年的挺身而出,而更加瑰丽。                                  ——《人民日报》


目录

堆排序:(以小堆为例)

 Heapsort函数(堆排序):

向下调整具体的时间复杂度:

向上调整具体的时间复杂度:

如何实现堆排序

TOP-K问题:


堆排序:(以小堆为例)

堆的分类:

  • 升序or降序
  • 大堆or小堆
void test2()
{//堆排序int array[] = { 27,15,19,18,28,34,65,49,25,37 };Heapsort(array, sizeof(array) / sizeof(array[0]));for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++){printf("%d ", array[i]);}printf("\n");}

 Heapsort函数(堆排序):

int array[] = { 27,15,19,18,28,34,65,49,25,37 };

需将这个数组进行大堆排列,分为两种调整形式:向上调整和向下调整

向上调整和向下调整的思想可以参考我的例外一篇博客:http://t.csdn.cn/YFSpd

void Ajustup(HPDataType*a, int child)
{//N*logNassert(a);//int child = n - 1;while (child > 0){int parent = (child - 1) / 2;if (a[child] > a[parent]){Swap(&a[child], &a[parent]);child = parent;}else{break;}}
}
void Ajustdown(HPDataType* a, int n,int parent)
{//O(N)assert(a);int child = 2 * parent+1;while (child<n){if (child + 1 < n && a[child] < a[child + 1])//  <假设左子树大{child++;}if (a[child] > a[parent])//>大堆,<为小堆{Swap(&a[child], &a[parent]);parent = child;child = child * 2 + 1;}else{break;}}
}

 向上调整和向下调整具体的时间复杂度是多少呢?

向下调整具体的时间复杂度:

假设树高为h

第h层,有2^(h-1)个节点,需要向下调整0次(直接不算,从第h-1层开始算)。

第h-1层,有2^(h-2)个节点,需要向下调整1层。

第h-2层,有2^(h-3)个节点,需要向下调整2层。

......

第4层,有2^3个节点,需要向下调整h-4层。

第3层,有2^2个节点,需要向下调整h-3层。

第2层,有2^1个节点,需要向下调整h-2层。

第1层,有2^0个节点,需要向下调整h-1层。

当h高的次数,最多调整层数为:

F(h)=2^0*(h-1)+2^1*(h-2)+2^2*(h-3)+...+2^(h-3)*2+2^(h-2)*1+2^(h-1)*0       ——①

2*F(h)=2^1*(h-1)+2^2*(h-2)+2^3*(h-3)+...+2^(h-2)*2+2^(h-1)*1+2^(h)*0       ——②

有错位相减②-①可得:

F(h)=-2^0*(h-1)+2^1+2^2+....+2^(h-2)+2^(h-1)

F(h)=2^h-1-h                                                                                                           ——③

 当树高为h时,节点总个数N为:

N=2^0+2^1+...+2^(h-2)+2^(h-1)

N=2^h-1                                                                                                                        ——④

有④可得:h=log(N+1)                                                                                            ——⑤

综合③④⑤可得:

F(N)=N-log(N+1)

  •  因此时间复杂度为O(N)

向上调整具体的时间复杂度:

在一层,需要向上调整0次

第二层,向上调整1次

第三层,向上调整2次

...

第h-1层,向上调整h-2次

第h层,向上调整h-1次

F(h)=2^1*1+2^2*2+....+2^(h-1)*(h-1)。

由错位相减可得:

F(N)=2N(1-log(N+1))。

  • 时间复杂度为O(N*logN)

如何实现堆排序

显然向下调整优于向上调整。

 先利用Ajustdown排序好数组,然后再用交换Ajustdown实现小堆。

void Heapsort(int*a,int n)//堆排序
{//向上调整for (int i = 1; i <n; i++){Ajustup(a, i);}//向下调整for (int i = (n - 1 - 1) / 2; i >= 0; i--){Ajustdown(a, n, i);}int end = n - 1;while (end>0){Swap(&a[0], &a[end]);Ajustdown(a, end, 0);end--;}//N*logN
}
void test2()
{//堆排序int array[] = { 27,15,19,18,28,34,65,49,25,37 };Heapsort(array, sizeof(array) / sizeof(array[0]));for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++){printf("%d ", array[i]);}printf("\n");}

TOP-K问题:

TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。

当数据量特别大时,我们造一个数组来存储他们依次存储时,就不大现实。

可以先开一个K个空间的数组,将这个数据量的前K个放进去,将他们小堆排列,并将这个数据量每个数与堆顶的元素相比较,比它大就替代它进入数组,在向下排列,以此循环。

void test3()
{int minHeap[5];FILE* fout = fopen("data.txt", "r");if (fout == NULL){perror("fopen fail");exit(-1);}int k = sizeof(minHeap) / sizeof(minHeap[0]);for (int i = 0; i < k; i++){fscanf(fout,"%d",&minHeap[i]);}for (int i = 0; i < sizeof(minHeap) / sizeof(minHeap[0]); i++){//检查是否录入数据printf("%d ", minHeap[i]);}printf("\n");for (int i = (k - 1 - 1) / 2; i >= 0; i--){Ajustdown(minHeap, k, i);}for (int i = 0; i < sizeof(minHeap) / sizeof(minHeap[0]); i++){//检查是否为大小堆printf("%d ", minHeap[i]);}printf("\n");int data = 0;while (fscanf(fout, "%d", &data) != EOF){if (data > minHeap[0]){minHeap[0] = data;Ajustdown(minHeap, k, 0);}}int end = k - 1;while (end > 0){Swap(&minHeap[0], &minHeap[end]);Ajustdown(minHeap, end, 0);end--;}//完成升序或者降序for (int i = 0; i < sizeof(minHeap) / sizeof(minHeap[0]); i++){//检查是否为大小堆printf("%d ", minHeap[i]);}printf("\n");fclose(fout);
}
void test4()
{int n, k;scanf("%d %d", &n, &k);FILE* fint = fopen("data1.txt", "w");if (fint == NULL){perror("fopen fail");exit(-1);}srand(time(0));int randK = k;for (size_t i = 0; i < n; ++i){int data = rand() % 100000;fprintf(fint, "%d\n", data);}fclose(fint);int* minHeap = (int*)malloc(sizeof(int) * k);FILE* fout = fopen("data1.txt", "r");if (fout == NULL){perror("fopen fail");exit(-1);}for (int i = 0; i < k; i++){fscanf(fout, "%d", &minHeap[i]);}for (int i = 0; i < k; i++){//检查是否录入数据printf("%d ", minHeap[i]);}printf("\n");for (int i = (k - 1 - 1) / 2; i >= 0; i--){Ajustdown(minHeap, k, i);}for (int i = 0; i < k; i++){//检查是否为大小堆printf("%d ", minHeap[i]);}printf("\n");int data = 0;while (fscanf(fout, "%d", &data) != EOF){if (data > minHeap[0]){minHeap[0] = data;Ajustdown(minHeap, k, 0);}}int end = k - 1;while (end > 0){Swap(&minHeap[0], &minHeap[end]);Ajustdown(minHeap, end, 0);end--;}//完成升序或者降序for (int i = 0; i < k; i++){//检查是否为大小堆,升序或者降序printf("%d ", minHeap[i]);}printf("\n");fclose(fout);
}
int main()
{//test1();test2();//test3();//test4();return 0;
}

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

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

相关文章

JVM类加载/双亲委派模型

类加载是一个复杂的过程, 那么我们平时说的类加载到底是干啥的呢? 一. 类加载是干啥的 我们都知道Java程序在运行之前, 需要进行编译, 由 .java > .class文件(二进制字节码文件) , 而在运行的时候呢, Java进程(JVM), 就会读取对应的 .class文件, 并且解析他的内容, 在内存…

【JY】 ABAQUS子程序UEL的有限元原理与应用

不等待即关注【简述ABAQUS中UEL子程序】ABAQUS作为成熟的商用有限元软件&#xff0c;可为高级用户提供特定的分析需求。ABAQUS常见的二次开发子程序包括&#xff1a;UMAT、VUMAT、UGENS、UEL和VUEL等。其中UEL/VUEL分别适用于ABAQUS的Standard/Explicit求解器。只有清楚有限元分…

C语言重点解剖关键字要点速记

1.在windows中&#xff0c;双击的本质是运行该程序&#xff0c;就是将程序(.exe)加载到内存当中去。任何程序在被运行之前都必须加载到内存当中去。 2.所有的变量本质都是在内存的某个位置开辟的。变量不能定义在硬盘上&#xff0c;因为变量必须在程序运行的时候才能被开辟&am…

软件设计师——项目管理

文章目录Gantt图与Pert图风险管理配置管理沟通管理题目举例Gantt图与Pert图 甘特图能够清晰描述每个任务的开始 / 结束时间及各任务之间的并行性&#xff0c;也可以动态地反映项目的开发进展情况&#xff0c;但难以反映多个任务之间存在的逻辑关系&#xff1b;PERT 利用项目的…

微机原理与接口技术笔记(持续更新)

文章目录前言储存系统与技术材料高速储存器缓冲储存器&#xff08;Cache&#xff09;材料&#xff0c;局部性&#xff0c;访问方式Cache全相联映射Cache交换与一致性单核CPU一致性处理多核CPU的MESI协议主储存器&#xff08;内存&#xff09;主要技术指标容量带宽内存模组与内存…

【C++进阶】C++11新特性上篇(万字详解)

&#x1f387;C学习历程&#xff1a;入门 博客主页&#xff1a;一起去看日落吗持续分享博主的C学习历程博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a; 也许你现在做的事情&#xff0c;暂时看不到成果&#xff0c;但不要忘记&…

[附源码]计算机毕业设计Python餐馆点餐管理系统(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

244. 谜一样的牛——二分+树状数组

有 n 头奶牛&#xff0c;已知它们的身高为 1∼n 且各不相同&#xff0c;但不知道每头奶牛的具体身高。 现在这 n 头奶牛站成一列&#xff0c;已知第 i 头牛前面有 Ai 头牛比它低&#xff0c;求每头奶牛的身高。 输入格式 第 1 行&#xff1a;输入整数 n。 第 2…n 行&#x…

UOS SDN

​ 文章目录 一.安装相关软件包二.上传并解压opendaylight软件包三.创建拓扑四.下发流表五.启动HTTP-server服务六.截图测试启动 OpenDayLight 的 karaf 程序,并安装如下组件: feature:install odl-restconf feature:install odl-l2switch-switch-ui feature:install odl-…

python制作问题搜索解答器,从此学习无忧

前言 大家早好、午好、晚好吖 ❤ ~ 今天博主给大家带来一个问题搜索解答器&#xff01;&#xff01; 需要素材 以及一双慧手和一个灵活的脑子~ 效果展示 代码展示 导入模块 import requests import tkinter as tk from tkinter import ttk import webbrowserdef search(wor…

Python中的魔法方法

python中的魔法方法是一些可以让你对类添加“魔法”的特殊方法,它们经常是两个下划线包围来命名的 Python的魔法方法&#xff0c;也称为dunder(双下划线)方法。大多数的时候&#xff0c;我们将它们用于简单的事情&#xff0c;例如构造函数(init)、字符串表示(str&#xff0c; r…

基于Geehy APM32F4移植使用letter-shell命令行终端

1. letter-shell简介 letter shell是一个C语言编写的&#xff0c;可以嵌入在程序中的嵌入式shell&#xff0c;主要面向嵌入式设备。 说得直白点他就是一个命令行交互软件&#xff0c;可以读取用户输入的命令&#xff0c;找到并执行命令对应的函数。 letter-shell的功能十分强…

XXL-Job分布式任务调度框架-- 集群HA的配置3

一 xxl-job集群概述 1.1 xxl-job集群HA的作用 为了避免单点故障&#xff0c;任务调度系统通常需要通过集群实现系统高可用 由于任务调度系统的特殊性&#xff0c;“调度”和“任务”两个模块需要均支持集群部署&#xff0c;由于职责不同&#xff0c;因此各自集群侧重点也有…

适合零基础人群学习的Python入门教程,快来学习吧

适合零基础人群学习的Python入门教程学什么&#xff1f;小编为大家准备的Python学习教程&#xff0c;课程主要讲解&#xff1a;Python核心编程、Linux基础、前端开发、Web开发、爬虫开发、人工智能等内容。 对于初学者想更轻松的学好Python开发&#xff0c;爬虫技术&#xff0c…

Go环境搭建与IDE开发工具配置

安装Go语言编译器 Go语言编译器》编译器将源代码编译为可执行程序》源代码程序员使用高级语言所书写的代码文件》高级语言c/c/go…》机器语言0和1构成&#xff0c;机器能直接识别》汇编语言比机器语言稍微可读一点点的指令集 编译器下载地址 根据系统下载对应的go编译器版本…

三分查找算法

目录 一 算法简介 详细介绍 两种基本方法 二 算法实践 1&#xff09;实数三分 拓展&#xff1a;秦九韶算法计算多项式 方法1&#xff1a;直接模拟累加 方法二&#xff1a;根据秦九韶算法 1&#xff09;模板三分法 题目描述 解法 2&#xff09;三分求极值 题目描述 …

Python:遗传算法最优路径

Hello&#xff0c;大家好&#xff01;读研前写过一篇遗传算法的代码&#xff0c;比较简单&#xff0c;算是个入门&#xff0c;当时就有想用它来解决最优路径的问题&#xff0c;上算法导论课时碰巧有听到同学有分享过&#xff0c;但由于自己研究的方向不是这块&#xff0c;就没有…

C# 绘图基本方法

一得到Graphics对象 1 OnPaint事件中使用 Protected overrid void OnPaint(PaintEventArgs e) {Graphics ge.Graphics;...... }2 其他情况实现 Graphics gthis.CreaateGraphics();二 关于Graphics的释放 1 对于CreateGraphics&#xff08;&#xff09;得到的Graphics对象&a…

【Linux权限】文件权限值,权限掩码,粘滞位,普通用户添加信任名单

目录 1.权限分为2种用户&#xff1a;超级用户&#xff0c;普通用户 2.文件类型和访问权限 ​3.权限掩码&#xff08;八进制&#xff09; 4.sudo短暂提升权限 5.粘滞位 1.权限分为2种用户&#xff1a;超级用户&#xff0c;普通用户 超级用户&#xff08;通常为root&#x…

ArcGIS Pro 加载项(5)——样式符号属性对调

之前是已经通过Python构建脚本工具&#xff0c;实现了stylx文件的符号属性的对调。 ArcGIS Pro脚本工具&#xff08;12&#xff09;——样式符号属性对调_学学GIS的博客-CSDN博客为地类做样式符号匹配经常碰到这样的问题&#xff1a;属性表里面只有地类代码&#xff0c;但是做…