堆《数据结构》

news2024/11/15 17:36:58

堆《数据结构》

  • 1. 堆排序
    • 1.1 建堆
      • 向上调整建堆
      • 向下调整建堆
    • 1.2 利用堆删除思想来进行排序
    • 1.3Top-k问题
  • 2.堆的时间复杂度

1. 堆排序

1.1 建堆

建大堆
建小堆

向上调整建堆

AdjustUp建堆

在这里插入图片描述

void AdjustUp(HPDataType* a, int child)
{
	// 初始条件
	// 中间过程
	// 结束条件
	int parent = (child - 1) / 2;
	//while (parent >= 0)
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

void headsport(int* a, int n)//建堆
{
	for (int i = 0;i < n;i++)
	{
		AdjustUp(a, i);//建堆(降序建大堆)向上调整建堆
	}
}
void test1()
{
	int arr[] = {1,5,3,2,7,9,4,6,8};
	headsport(arr, sizeof(arr) / sizeof(arr[0]));
	for (int i = 0;i < sizeof(arr) / sizeof(arr[0]);i++)
	{
			printf("%d", arr[i]);
	}

}

1:我们通过AdjustUp函数来建堆
2:在控制AdjustUp函数中a[child] < a[parent]的大小比较关系,这是控制建小堆,还是建大堆

如:a[child] < a[parent] 建小堆
在这里插入图片描述
a[child] > a[parent]建 大堆
在这里插入图片描述

向下调整建堆

AdjustDown

在这里插入图片描述
在这里插入图片描述

void AdjustDown(HPDataType* a, int n, int parent)
{
	// 先假设左孩子小
	int child = parent * 2 + 1;

	while (child < n)  // child >= n说明孩子不存在,调整到叶子了
	{
		// 找出小的那个孩子
		if (child + 1 < n && 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 headsport(int* arr, int n)
{
	//时间复杂度O(N)
	for (int i = (n-1-1)/2;i >=0;i--)
	{
		AdjustDown(arr,n,i);//向下调整建堆
	}


}
void test1()
{
	int arr[] = {1,5,3,2,7,9,4,6,8};
	headsport(arr, sizeof(arr) / sizeof(arr[0]));
	for (int i = 0;i < sizeof(arr) / sizeof(arr[0]);i++)
	{
			printf("%d", arr[i]);
	}

}

与AdjustUp同理:
arr[child]>arr[parent]->大堆
在这里插入图片描述
arr[child]<arr[parent]->小堆
在这里插入图片描述

1.2 利用堆删除思想来进行排序

1:建堆
升序:建大堆
降序:建小堆
2:建堆和堆删除中都用到了向下调整,因此掌握了向下调整,就可以完成堆排序。

实现图:
在这里插入图片描述

void headsport(int* arr, int n)
{
	for (int i = (n-1-1)/2;i >=0;i--)
	{
		AdjustDown(arr,n,i);//向下调整建堆
	}
	int end = n - 1;//取最后一位数据
    while (end > 0)
{
	Swap(&arr[0], &arr[end]);//交换
	AdjustDown(arr, end, 0);//在向下建堆
	end--;
}
}
void test1()
{
	int arr[] = {1,5,3,2,7,9,4,6,8};
	headsport(arr, sizeof(arr) / sizeof(arr[0]));
	for (int i = 0;i < sizeof(arr) / sizeof(arr[0]);i++)
	{
			printf("%d", arr[i]);
	}

}
int main()
{
	test1();
	//CreateNdDate();
	/*TestHeap();*/
	/*TestHeap3();*/
	return 0;
}

1.3Top-k问题

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

对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据
量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:

1.用数据集合中前K个元素来建堆

·前k个最的元素,则建小堆
·前k个最的元素,则建大堆

2.用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素

将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素

#include<time.h>
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
void CreateNdDate()
{
	//造数据
	int n = 100000;
	srand(time(0));//随机种子
	const char* file = "daf.txt";
	FILE* fin = fopen(file, "w");//打开文件
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}
	for (int i = 0;i < n;i++)
	{
		int x = (rand() + i) % 1000000;//随机值
		fprintf(fin, "%d\n", x);//写入数据
	}
	fclose(fin);
}

void TestHeap()
{
	int k;//获取前k个数
	printf("请输入k>");
	scanf("%d", &k);
	int* kminheap = (int*)malloc(sizeof(int) * k);
	if (kminheap == NULL)
	{
		perror("mallco fail");
		return;
	}
	const char* file = "data.txt";
	FILE* fout = fopen(file, "r");
	if (fout == NULL)
	{
		perror("fopen error ");
		return;
	}
	//读取文件前k个数
	for (int i = 0;i < k;i++)
	{
		fscanf(fout,"%d", &kminheap[i]);
	}
	for (int i = (k - 1 - 1) / 2;i >= 0;i--)//建小堆
	{
     AdjustDown(kminheap, k, i);
	}
	//读取剩下n-k个数
	int x = 0;
	while (fscanf(fout,"%d", &x)>0);
	{
		if (x > kminheap[0])
		{
			kminheap[0] = x;
			AdjustDown(kminheap, k, 0);
		}
	}
	printf("最大前k个\n");
	for (int i = 0;i < k;i++)
	{
		printf("%d\n", kminheap[i]);
	}

}
int main()
{
	
	CreateNdDate();
	TestHeap();
	
	return 0;
}

在这里插入图片描述

2.堆的时间复杂度

因为堆是完全二叉树,而满二叉树也是完全二叉树,此处为了简化使用满二叉树来证明(时间复杂度本来看的就是近似值,多几个结点不影响最终结果):

向下调堆:从最后一个根节点开始调整
在这里插入图片描述
在这里插入图片描述

向上调堆:

调整次数:
第二层:向上调整 1次
第三层: 向上调整2次


第n层:向上调整n次

节点个数
第一层:2^0个
第二层:2^1个


第n层:2^n-1个

在这里插入图片描述

感谢大家观看!!!

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

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

相关文章

专利权和版权有什么区别?

专利权和版权有什么区别&#xff1f;

【IEEE】第四届智能通信与计算国际学术会议(ICICC 2024,10月18-20)

第四届智能通信与计算国际学术会议&#xff08;ICICC 2024&#xff09;将于2024年10月18-20日在中国郑州隆重举行。 会议旨在为从事智能通信与计算研究的专家学者、工程技术人员、技术研发人员提供一个共享科研成果和前沿技术&#xff0c;了解学术发展趋势&#xff0c;拓宽研究…

帆软报表,达梦数据库驱动上传失败

1、按照正常操作新建数据库连接&#xff0c;上传准备好的达梦驱动时&#xff0c;提示如图一需要修改SystemConfig.driverUpload为true才可以。 2、FineDB存储了数据决策系统中除平台属性配置以外的所有信息。详情请参见&#xff1a; FineDB 数据库简介。 3、因此管理员可通过…

都2024年了,你还在手动敲SQL吗?试试这款开源免费的AI数据库!

​ ✍️作为一名开发人员&#xff0c;基本上每天都要和数据库打交道&#xff0c;无论是设计表结构、执行查询还是调试应用中的数据问题。长期以来&#xff0c;我一直在使用诸如DBeaver、Navicat和DataGrip这样的数据库管理工具。尽管这些工具各有千秋&#xff0c;但在面对复杂的…

python怎么使用模块中的类

Chain.py是模块&#xff08;Module&#xff09;&#xff0c;在代码里定义的Class Chain是在模块里定义的类。 一种方法是&#xff1a; from Chain import Chain 还有一种方法是&#xff1a; a Chain.Chain() 相当于从模块里索引出这个类&#xff0c;两种方法都可以。

3b1b自注意力机制讲解记录

本文是对视频【官方双语】直观解释注意力机制&#xff0c;Transformer的核心 | 【深度学习第6章】的整理 1 背景 要解决的问题&#xff1a;接收一段文本&#xff0c;预测下一个词 句子会被切成许多小块&#xff0c;这些小块称为token。token可以是单词也可以是词组。为了简单…

SpringBoot百万行Excel导入MySQL实践

在公司开发时&#xff0c;客户说需要支持大数据量excel导入&#xff0c;所以打算写一篇文章记录下思路和优化过程。 一、前期准备 首先我们选用的肯定是阿里出品的EasyExcel&#xff0c;对比poi和jxl占内存更少 easyexcel官方网站准备测试的数据库和excel文件&#xff0c;已经…

Zustand:让React状态管理更简单、更高效

Zustand 这个单词在德语里是状态的意思&#xff08;发音&#xff1a;促stand&#xff09; 1. 下载zustand npm i zustand 或者 yarn add zustand2.创建一个store import { create } from zustandconst useBearStore create((set) > ({bears: 0,increasePopulation: …

20240824给飞凌OK3588-C的核心板刷Ubuntu22.04并连接adb

20240824给飞凌OK3588-C的核心板刷Ubuntu22.04并连接adb 2024/8/24 15:56 缘起&#xff0c;由于我司对面积有极度的追求&#xff0c;所以将飞凌OK3588-C开发板使用的【9线】type-C接口&#xff08;USB3.1?&#xff09;降级为4线的USB2.0。 【micro USB/MINI USB。】 先决条件…

基于RK3588的多摄像头车辆与车道线检测系统(基于rk3588的车辆和车道线检测,可以带四个720p的摄像头,2个1080p的摄像头)

硬件配置&#xff1a; 处理器&#xff1a;Rockchip RK3588&#xff0c;这是一款高性能的嵌入式处理器&#xff0c;支持多路高清视频输入和处理。摄像头配置&#xff1a; 4个720p&#xff08;1280x720&#xff09;分辨率的摄像头2个1080p&#xff08;1920x1080&#xff09;分辨…

什么是持续集成(持续交付、部署)

文章目录 1 持续集成1.1 持续集成的好处1.2 持续集成的目的1.3 没有持续集成的状况 2 持续交付3 持续部署4 持续交付和持续部署的区别 1 持续集成 持续集成&#xff08;Continuous integration&#xff0c;简称CI&#xff09;&#xff0c;简单来说持续集成就是频繁地&#xff…

拓扑排序,以及区间dp相关试题

目录 1.有向无环图(DAG图&#xff09; 2.AOV网:顶点活动图 3.拓扑排序 4.实现拓扑排序 力扣.207课程表 牛客.最长回文子序列 1.有向无环图(DAG图&#xff09; 入度:表示有多少条边指向它 出度:有多少条边向外指出他 2.AOV网:顶点活动图 3.拓扑排序 找到做事情的先后顺序 …

React学习笔记(三)——redux状态管理工具

1. Redux快速上手 1.1 什么是Redux&#xff1f; Redux 是 React 最常用的 集中状态管理工具 &#xff0c;类似于 Vue 中的 Pinia&#xff08;Vuex&#xff09;&#xff0c; 可以独立于框架运行 作用&#xff1a; 通过集中管理的方式管理应用的状态 1.2 Redux快速体验 不和任何…

【OpenGL学习笔记】--图像管线

图像管线&#xff08;Image Pipeline&#xff09;是计算机图形学中一个核心概念&#xff0c;尤其是在图形处理和渲染的上下文中。它是一个用于处理和渲染图像的流程&#xff0c;其中包括从场景数据的输入到最终图像输出的各个阶段。 图像管线的组成 顶点处理&#xff08;Verte…

大模型入门到精通——使用Embedding API及搭建本地知识库(一)

使用Embedding API及搭建本地知识库 1. 基于智谱AI调用Embedding API实现词向量编码 首先&#xff0c;生成.env 文件&#xff0c;填写好智谱AI的API-key 参考&#xff1a;大模型入门到实战——基于智谱API key 调用大模型文本生成 读取本地/项目的环境变量。 find_dotenv(…

基于SSM的在线家教管理系统的设计与实现 (含源码+sql+视频导入教程+论文+PPT)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的在线家教管理系统拥有三个角色 管理员&#xff1a;用户管理、教师管理、简历管理、申请管理、课程管理、招聘教师管理、应聘管理、评价管理等 教师&#xff1a;课程管理、应聘…

Prometheus Operator部署管理

Prometheus Operator部署管理 Prometheus Operator & Kube-Prometheus & Helm chart 部署区别 Prometheus Operator 是 Kubernetes 原生的工具&#xff0c;它通过将 Prometheus 资源定义为 Kubernetes 对象&#xff08;CRD&#xff09;来简化 Prometheus 集群的管理。…

如何使用ssm实现公司项目管理系统设计与实现

TOC ssm136公司项目管理系统设计与实现jsp 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规…

Avg函数求比率的应用(SQL)

题目 在 SQL 中&#xff0c;AVG 函数用于计算一组数值的平均值。这个功能也可以用来计算比率或比例。 平均值 可以用来计算比率的原因&#xff1a; 二元值&#xff1a;在许多情况下&#xff0c;我们用 1 和 0 表示发生或未发生的事件。例如&#xff0c;在你的查询中&#xff0…

基于Java的C语言课程教学实践小程序的设计与实现(论文+源码)_kaic

基于Java的C语言课程教学实践小程序的设计与实现 摘 要 在当前信息技术迅猛发展的大背景下&#xff0c;为了学生更好地利用信息技术学习C语言&#xff0c;急需开发一款C语言课程教学实践小程序。‎这个小程序可以让学生不再局限于课堂学习‎的教学模式&#xff0c;而是能够随…