【数据结构与算法】之堆的应用——堆排序及Top_K问题!

目录

1、堆排序

2、Top_K问题

3、完结散花


                                                                                个人主页:秋风起,再归来~

                                                                                            数据结构与算法                             

                                                                       个人格言:悟已往之不谏,知来者犹可追

                                                                                        克心守己,律己则安!

1、堆排序

对一个无序的数组,因为数组中的元素是连续的,那我们就可以将数组中的元素进行建堆排序!

假设我们要对一个数组中的元素进行降序,那我们就要先将其进行向下调整建小堆,再将堆顶元素与堆的最后一个元素交换,那么数组中最小的那个元素就到最后面去了,最后一个数有序后,那我们就不再把它看作堆的元素了,最后再在堆顶进行向下调整保证小堆不变。这是一趟,假设数组中有N个元素,那我们进行(N-1)趟就行了。

下面是图解:

 代码:

//交换
void swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

//向上调整
void AdjustUp(int* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])//< 建小堆;> 建大堆
		{
			swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

//向下调整
void AdjustDown(int* 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[child] < a[parent])//建小堆,即小的当父亲
		{
			swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

//堆排序
void HeapSort(int* a, int len)
{
	//建堆算法一(从第一个孩子向上调整)
	//这种写法的时间复杂度为n*logn
	//for (int i = 1; i < len; i++)
	//{
	//	AdjustUp(a, i);//从第一个孩子向上调整建堆
	//}
	// 
	//建堆算法二(从倒数第一个根向下调整)
	//这种写法的时间复杂度为O(N)[更优]
	for (int i = (len-1-1)/2; i >= 0; i--)
	{
		AdjustDown(a, len,i);//从倒数第一个根向下调整建堆
	}
	int end = len - 1;
	while (end > 0)
	{
		swap(&a[0], &a[end]);//交换第一个数与最后一个数
		end--;
		AdjustDown(a, end, 0);
	}
}

int main()
{
	int a[] = { 1,2,4,5,6,8,9,10 };
	int len = sizeof(a) / sizeof(a[0]);
	HeapSort(a, len);
	for (int i = 0; i < len; i++)
	{
		printf("%d ", a[i]);
	}
	return 0;
}

 

2、Top_K问题

 Top_K问题:

Top_K问题就是在大量数据中找出最大或最小的前K个

我们可以很轻松的想到用将这些全部数据进行建堆,在进行K次pop,这样我们就很容易的就可以找到最大或最小的前K个。但这里有一个问题,就是存储这么的数据势必会用到大量的空间,那我们有没有其他方法,在用到极小的的空间内解决问题呢?

当然可以!

假设我们要找出最大的前K个~

1、我们先将全部数据的前K个建成小堆

2、再将后N-K个数据分别和堆顶数据比较,比堆顶数据大就将堆顶数据覆盖

3、然后再从堆顶向下调整保持小堆结构

4、将后N-K个数据比较完后,小堆里面的数据就是最大的前K个

我这里先随机生成10万个随机数并且这些随机数都小于10万,并将这些数据都写进我们的文本文件中!

void CreatRandomNumber()
{
	FILE* pf = fopen("test.txt", "w");
	if (pf == NULL)
	{
		perror("fopen fail!\n");
		return;
	}
	srand((unsigned int)time(NULL));
	int n = 100000;//随机生成10万个数
	for (int i = 0; i < n; i++)
	{
		int x = (rand() + i) % 100000;//这些数的大小都小于10万(方便后面检测)
		fprintf(pf, "%d\n", x);//将数据写入文件当中
	}
	fclose(pf);
}
void TestTopK()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen fail!\n");
		return;
	}
	int k = 0;
	printf("请输入您要的前K个数:");
	scanf("%d", & k);
	int* HeapTopK = (int*)malloc(sizeof(int) * k);
	//在文件中读取K个数放到数组中
	for (int i = 0; i < k; i++)
	{
		fscanf(pf, "%d", &HeapTopK[i]);
	}
	//将这K个数建小堆
	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(HeapTopK, k, i);//向下调整建堆
	}
	int x = 0;
	//在10万个数中找前K个数
	while (fscanf(pf, "%d", &x)>0)
	{
		if (x > HeapTopK[0])
		{
			HeapTopK[0] = x;
			AdjustDown(HeapTopK, k, 0); 
		}
	}
	HeapSort(HeapTopK, k);
	//打印前k个数
	for (int i = 0; i < k; i++)
	{
		printf("%d ", HeapTopK[i]);
	}
	free(HeapTopK);
	HeapTopK = NULL;
	fclose(pf);
}
int main()
{
	//CreatRandomNumber();
	TestTopK();
	return 0;
}

为了检查结果是否准确,我在文件中随机将10个数的大小手动调整成大于十万!

让我们来看看结果!

3、完结散花

好了,这期的分享到这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

​​​​

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

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

相关文章

安卓开发--安卓使用Echatrs绘制折线图

安卓开发--安卓使用Echatrs绘制折线图 前期资料安卓使用Echarts绘制折线图1.1 下载 Echarts 安卓资源1.2 新建assets文件1.3 新建布局文件1.4 在布局文件中布局WebView1.5 在活动文件中调用 最终效果 前期资料 Echarts 官网样式预览: https://echarts.apache.org/examples/zh/…

Java开发者必知的时间处理工具:SimpleDateFormat类详解

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

【论文阅读】 YOLOv10: Real-Time End-to-End Object Detection

文章目录 AbstractIntroductionRelated WorkMethodologyConsistent Dual Assignments for NMS-free Training &#xff08;无NMS训练的一致性双重任务分配&#xff09;Holistic Efficiency-Accuracy Driven Model Design &#xff08;效率-精度驱动的整体模型设计&#xff09; …

ABB 任务 模块 程序

1&#xff0c;任务由模块组成 &#xff0c; 2&#xff0c;模块分为程序模块和系统模块 3&#xff0c;可以通过新建程序模块和删除程序模块 4.可以在程序模块中构建程序 5&#xff0c;系统模块不能够被删除 6&#xff0c;main 程序主要体现在自动运行中

C++—— set、map、multiset、multimap的介绍及使用

目录 关联式容器 关联式容器的特点和使用场景 树形结构与哈希结构 树形结构 哈希结构 键值对 set set的介绍 set的定义方式 set的使用 multiset map map的介绍 map的定义方式 map的使用 multimap 关联式容器 C标准模板库&#xff08;STL&#xff09;中的关联…

【2024最新华为OD-C卷试题汇总】传递悄悄话的最长时间(100分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; 文章目录 前…

Mysql插入中文内容报错解决及其Mysql常用的存储引擎说明

一、问题描述 我们在Mysql数据库的表中插入带有中文内容时报错,提示【1366 - Incorrect string value: \xE5\x8C\x97\xE4\xBA\xAC... for column UserDealer at row 1】,如下图所示: 二、问题分析 一般来说插入中文内容有问题我们首先想到的就是编码问题;我们可以查看该表使…

C语言之指针进阶(3),函数指针

目录 前言&#xff1a; 一、函数指针变量的概念 二、函数指针变量的创建 三、函数指针变量的使用 四、两段特殊代码的理解 五、typedef 六、函数指针数组 总结&#xff1a; 前言&#xff1a; 本文主要讲述C语言指针中的函数指针&#xff0c;包括函数指针变量的概念、创建…

git分支策略(github-flow VS git flow,如何选择)

一. 结论 Github flow&#xff1a;最简单 小型项目&#xff0c;持续部署&#xff0c;自动化测试程度高&#xff0c;发布流程简单 Git flow&#xff1a;复杂但最常用 大型项目&#xff0c;发布周期长&#xff0c;需要同时维护多个版本&#xff0c;发布流程复杂 表格提供了不…

【算法设计与分析】基于Go语言实现动态规划法解决TSP问题

本文针对于最近正在学习的Go语言&#xff0c;以及算法课实验所需内容进行Coding&#xff0c;一举两得&#xff01; 一、前言 由于这个实验不要求向之前的实验一样做到那种连线的可视化&#xff0c;故可以用图形界面不那么好实现的语言进行编写&#xff0c;考虑到Go语言的…

2、xss-labs之level2

1、打开页面 2、传入xss代码 payload&#xff1a;<script>alert(xss)</script>&#xff0c;发现返回<script>alert(xss)</script> 3、分析原因 打开f12&#xff0c;没什么发现 看后端源码&#xff0c;在这form表单通过get获取keyword的值赋给$str&am…

下雨!大水蚁引发的水文!看比赛咯,曼联VS曼城——早读(逆天打工人爬取热门微信文章解读)

唠唠嗑 水一水 引言Python 代码结尾 引言 今天星期六 大小周 一个等了很久的双休 昨天晚上真的是吓到我了 漫天的小飞虫 我一开始还以为是一两只 没想到那些小飞虫 从阳台不断飞进来 在山卡拉下面租房子 也是太恐怖了 来个特写 他们也就一个晚上的时间 成虫 天气合适 长翅…

使用docker commit创建新镜像

前言 我们知道&#xff0c;从docker-hub上拉取的镜像所创建的容器是最小版本的&#xff0c;比如ubuntu内部是没有vim编辑器的&#xff0c;我们需要自己手动安装&#xff0c;但是当我们安装后假如有人把我们的容器误删了&#xff0c;那么我们再次根据原始镜像创建的容器就没有了…

优先级队列(堆)的实现

1.什么是优先级队列 队列是一种先进先出(FIFO)的数据结构&#xff0c;但有些情况下&#xff0c;操作的数据可能带有优先级&#xff0c;一般出队 列时&#xff0c;可能需要优先级高的元素先出队列&#xff0c;该中场景下&#xff0c;使用队列显然不合适&#xff0c;比如&#x…

Drone+Gitee自动执行构建、测试和发布工作流

拉取Drone:(至于版本&#xff0c;你可以下载最新的) sudo docker pull drone/drone:2 拉取runner&#xff1a; sudo docker pull drone/drone-runner-docker 在Gitee中添加第三方应用&#xff1a; 进入个人主页&#xff0c;点击设置&#xff1a; 往下翻&#xff0c;找到数…

2022蓝桥杯大赛软件类国赛Java大学B组 左移右移 空间换时间+双指针

import java.util.Scanner;public class Main {static Scanner scnew Scanner(System.in);public static void main(String[] args) {int nsc.nextInt();//数组长度int tsc.nextInt();//操作次数int arr[]new int[n];char arr1[] new char[t];int arr2[] new int[t];int vis…

输入一串字符,输入想要字符串前*的个数n,判断字符串前*的个数是大于n还是小于n,如果大于n则删除多余的*其它保持不变,如果小于n,则字符串也保持不变

#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> void fun(char* a, int n) {int i 0, j 0, m 0,b0,c0;char* p;p a;//第一步&#xff0c;判断字母前面有多少个*while (p[i] *){j;}printf("字母前*的个数%d\n",j);//求总的字符串长度while (a[m] !…

基于.net开发的博客系统

基于.net开发可以批量上传md文件生成文章的博客系统 .NET 个人博客 基于.net开发的博客系统 个人博客系统&#xff0c;采用.net core微服务技术搭建&#xff0c;采用传统的MVC模式&#xff0c;使用EF core来对mysql数据库(sqlite数据库)进行CRUD操作项目 为什么要自己开发博客…

csdn的insCode怎么用IDE和linux终端

1.进入insCode&#xff0c;选择工作台 找到我的项目&#xff0c;没有项目的话可以新建一个。 选择在IDE中编辑&#xff0c;界面如下&#xff1a; 右边有个终端&#xff0c;点击即可出现linux的xterm终端。

依赖的各种java库(工具类) :fastjson,lombok,jedis,druid,mybatis等

lombok 功能&#xff1a; Lombok 是一个实用的Java类库&#xff0c;可以通过简单的注解来简化和消除一些必须有但显得很臃肿的Java代码。 导入包&#xff1a;使用Lombok首先要将其作为依赖添加到项目中&#xff0c;在pom.xml文件中手动添加 <dependency><groupId&g…