数据结构:堆的算法

news2024/9/22 19:30:39

目录

  • 一堆的向上调整算法
  • 二堆的向下调整算法
  • 三堆的应用:堆排序
  • 四TOPK问题

一堆的向上调整算法

我们在堆中插入一个数据一般实在堆的最后插入然后可以一步一步与上层结点(父结点进行比较),继而进行交换,完成二叉树的结构,

在这里插入图片描述
其中我们就有公式父节点的下标=(孩子结点的下标-1)/2就等价于parent=(child-1)/2

我们可以写一个方法让插入的数据与父结点进行比较直到合适的位置为止。

那么停下来就有两种情况:
1一直交换到头结点停下。2交换到合适的位置但没有到头结点,中途停下。

第一种情况一直到头结点,因为每次都要

child=parent;
parent = (child - 1) / 2;

所以当child到0没有父结点了就循环结束。

void AdjustUp(HeapType* 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;

			}

		}

	}


第二种情况因为中点调整好了当if语句没交换时候就可以结束循环调整完成了

加上else
{
break;
}

void AdjustUp(HeapType* 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;
			}

		}

	}


二堆的向下调整算法

当我们要去删除一个大堆或者小堆的头结点的时候我们可以直接把尾部结点的数据和头部的交换,然后把访问下标的数字-1.然后进行向下调整,这样就可以建立二叉树的结构了

但是 我们有一个问题,我们都知道parent=(child-1)/2,且有唯一一个父节点。但是我们让头结点进行向下调整的时候要去交换哪个孩子结点呢?是否要判断?

在这里插入图片描述

如图这是个小堆,头结点进行向下调整的时候需要判断跟哪个孩子交换,必须保证是次小的孩子,要不然就会出现父节点比孩子结点大,就不是小堆了。大堆也是同样道理

判断代码如下

if (child + 1 < n && a[child] > a[child + 1]) {
	child = child + 1;

其中n是有效数据个数,需要保证有两个孩子才能判断
向下调整算法代码如下

void AdjustDown(HeapType* a, int parent, int n) {
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child] > a[child + 1]) {
			child = child + 1;


		}
		if (a[parent] > a[child]) {
			Swap(&a[parent], &a[child]);
			parent = child;
			child = child * 2 + 1;
		}
		else
		{
			break;
		}

	}

}

三堆的应用:堆排序

那么我们可以通过堆的结构来进行排序,因为二叉树不是严格意义上的顺序结构它只保证父节点比孩子结点大或小。
我们可以实现一个算法来把堆的二叉树结构调整为升序或者降序。

具体实现方法为,循环把头结点和尾结点进行交换,因为头结点是一个结构最大或者最小的,这时候我们把尾部结点减少一个,在进行向下调整,然后再进行交换,把次大或次小的数据放到最后一个,尾部结点减少一个,向下调整…如此循环直到到最后一个数据向下调整。这样就变成有序的了。
因为大堆的头结点是最大的,一开始放到尾结点,这样就是升序,反之小堆调整则为降序。

HeapSort2(a1, 6);
int sz = sizeof(a1) / sizeof(a1[0]);
for (int i = 0; i < sz; i++) {
	printf("%d ",a1[i]);
}
void HeapSort2(HeapType* arr, int n) {//进行向下调整建堆

	for (int i = (n - 1 - 1) / 2; i >= 0; i--) {


		AdjustDown(arr, i, n);

}
	int end = n - 1;
	for (int i = end; i > 0; i--) {//小堆进行调整为降序
		Swap(&arr[0], &arr[end]);
		AdjustDown(arr, 0, end);
		end--;



	}
}

在这里插入图片描述

四TOPK问题

我们在N个数据中找前topk大或者小的数据这类问题一般思路就是一个个进行比较,这样空间复杂度太大。

我们可以先建立一个大小为k的堆,然后通过后N-k个数据依次和堆的头结点进行比较,判断是否入堆,如果入堆就向下调整到合适位置,这样数据读完我们就可以销毁文件,那么空吉安复杂度则只有建立的堆,然后堆的数据即为topk.

我们可以进行文件输入输出流来实现创造 N个数据
中间利用time函数,利用写的方式把数据写道date,txt文件中
大小为不大于等于1000000

void CreateNDate()
{
	// 造数据
	int n = 10000;
	srand(time(0));
	const char* file = "data.txt";
	FILE* fin = fopen(file, "w");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}

	for (size_t i = 0; i < n; ++i)
	{
		int x = rand() % 1000000;
		fprintf(fin, "%d\n", x);
	}

	fclose(fin);
}

然后读取数据,建立k个大小的堆,再把文件后面数据和堆顶比较,如果比堆顶大就进堆,然后向下调整。

void PrintTopK() {
	int k = 0;
	printf("请输入");
	scanf("%d",&k);
	const char* file = "data.txt";
	FILE* fout = fopen(file, "r");
	if (fout == NULL) {
		perror("error");
	}
	HeapType* pp = (HeapType*)malloc(k * sizeof(HeapType));

	
	for (int i = 0; i < k; i++) {

		fscanf(fout, "%d", &pp[i]);

	}
	for (int i = (k - 1 - 1) / 2; i >= 0; i--) {


		AdjustDown(pp, i, k);
	}
	int x=0;
	while (fscanf(fout, "%d", &x) != EOF) {
		if (x > pp[0]) {
			pp[0] = x;
			AdjustDown(pp, 0, k);
		}
	}
	for (int i = 0; i < k;i++)  {


		printf("%d ", pp[i]);
	}

	fclose(fout);



}

我们为了验证对不对可以修改两个数超过1000000,然后输出看对不对
最后输出结果

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

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

相关文章

Spring Cloud之三 网关 Gateway

1:Intellij 新建项目 spring-cloud-gateway 2:pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLoca…

Vulnhub靶场 DC-2

靶机地址:https://www.vulnhub.com/entry/dc-2,311/ 导入到VMware里面去, 设置NAT模式 namp扫描一下c段获取ip地址, 然后再扫描ip地址获取详细的信息 得到ip 192.168.75.134 无法访问 按照下面这个方法可以访问了 在kali上的处理 flag1 网站上就存在 提示了一个cewl工具,…

【Unity踩坑】使用Input System后UI EventSystem的冲突

在项目中使用Input System&#xff0c;在UI中添加了元素后&#xff0c;再次运行出现下面的错误&#xff1a; InvalidOperationException: You are trying to read Input using the UnityEngine.Input class, but you have switched active Input handling to Input System pac…

基于SpringBoot+Vue+MySQL的考编论坛网站

系统展示 用户前台界面 管理员后台界面 系统背景 在当前信息化高速发展的时代&#xff0c;考编已成为众多求职者的重要选择。然而&#xff0c;备考过程中信息获取、经验交流及资源分享的需求日益凸显。基于SpringBoot、Vue.js与MySQL构建的考编论坛网站应运而生&#xff0c;旨在…

微软面向所有用户推出 Xbox Game Pass Standard

2024 年 8 月下旬&#xff0c;微软启动了 Xbox Game Pass Standard 的公开测试&#xff0c;这是其不断发展的 Game Pass 套餐中的一个新层级。几周后的今天&#xff0c;Xbox Game Pass 标准版已向支持地区的所有 Xbox 用户开放。 Xbox Game Pass 标准版每月收费 14.99 美元。以…

【可测试性实践】C++ 单元测试代码覆盖率统计入门

引言 最近在调研C工程怎么做单元测试和代码覆盖率统计&#xff0c;由于我们工程有使用Boost库&#xff0c;尝试使用Boost.Test来实现单元测试并通过Gcov和Lcov来生成代码覆盖率报告。本文记录完整的搭建测试Demo&#xff0c;希望能带来一定参考。 常用C单测框架对比 特性Goo…

实时系统资源监测:AutoPowerOptionsOK确保电脑性能与节能兼备

科技赋予生活翅膀&#xff0c;让我们在快节奏中翱翔&#xff0c;协调工作与梦想&#xff0c;让每一个梦想都有机会照进现实&#xff0c;绽放光彩——科技的进步不仅推动了社会的发展&#xff0c;也极大地改善了人们的日常生活。在众多科技成果中&#xff0c;电脑作为信息处理的…

Day8 | Java框架 | Maven

Day8 | Java框架 | Maven 分模块开发与设计分模块开发意义分模块开发步骤&#xff08;模块拆分&#xff09; 依赖管理概念依赖传递可选依赖与排除依赖 继承与聚合聚合继承 属性属性配置与使用资源文件引用属性版本管理 多环境配置与应用多环境开发跳过测试&#xff08;了解&…

场外期权是什么?个人可以参与场外期权交易吗?

今天期权懂带你了解场外期权是什么?个人可以参与场外期权交易吗?通过了解场外期权的特点、优点和缺点&#xff0c;投资者可以更好地决定是否使用这种工具进行风险管理或投资操作。 场外期权是什么? 场外期权是指通过私下协商而非在公开交易所交易的期权合约。以下是关于场…

Python基础语法(1)下

输入输出 和用户交互 程序需要和用户进行交互。 用户把信息传递给程序的过程&#xff0c;称为 "输入"&#xff0c;也就是用户给计算机下命令就叫做输入。 程序把结果展示给用户的过程&#xff0c;称为 "输出"&#xff0c;也就是计算机在向用户汇报工作…

【Hot100】LeetCode—139. 单词拆分

目录 1- 思路题目识别完全背包-动规五部曲 2- 实现⭐单词拆分——题解思路 3- ACM 实现 原题链接&#xff1a;139. 单词拆分 1- 思路 题目识别 识别1 &#xff1a;字符串 和一个 字符串数组 判断识别2&#xff1a;判断字符串能不能由字符串数组拼接形成&#xff0c;返回 true…

SprinBoot+Vue房屋租赁管理系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…

C语言练习题3

1.if语句 /*if语句*/ #include<stdio.h> int main() {int a 10;int b 12;if (a < b) {printf("%d", a);}return 0; }if语句&#xff1a;是条件判断语句。根据小括号中的条件判断该语句中的代码是否执行。如果符合判断的条件就执行&#xff0c;不符合则跳…

零基础国产GD32单片机编程入门(二十一)系统时钟频率配置实战含源码

文章目录 一.概要二.GD32F103C8T6单片机时钟源介绍二.GD32F103C8T6单片机外部高频晶振配置三.GD32F103C8T6单片机内部高频晶振配置四.GD32F103C8T6单片机使用内部8M晶振实验五.工程源代码下载六.小结 一.概要 GD32单片机的时钟源包括多种选项&#xff0c;时钟控制单元提供了一…

滑动窗口+动态规划

前言&#xff1a;分析这个题目的时候&#xff0c;就知道要这两个线段要分开&#xff0c;但是要保证得到最优解&#xff0c;那么我们在选取第二根线段的时候&#xff0c;要保证我们第一根线段是左边最优解 并且我们选的两根线段的右端点一定是我们的数组的点&#xff08;贪心思…

SprinBoot+Vue校园车辆管理系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…

HTML中的文字与分区标记

1.font标记&#xff1a;用来设置文字的字体&#xff0c;大小&#xff0c;颜色&#xff0c;等属性 <!--font:font标记用来设置字体大小颜色属性size:设置字号&#xff0c;默认是3号&#xff0c;1表示4号&#xff0c;-1表示2号&#xff0c;取值范围是[1,7]或[-7,-1]color:设置…

实战案例(4)如果想限制某些终端能上网,哪些不能上网有什么方法呢?

案例四&#xff1a;如果想限制某些终端能上网&#xff0c;哪些不能上网有什么方法呢&#xff1f; 实际中有这样的需求&#xff0c;客户那边希望某些区域只能boss上网或者boss随时都可以上&#xff0c;但是员工需要休息时间才能上&#xff0c;针对这样的需求我们来看看怎么去实现…

Leetcode3271. 哈希分割字符串

Every day a Leetcode 题目来源&#xff1a;3271. 哈希分割字符串 解法1&#xff1a;模拟 按题意模拟。 代码&#xff1a; /** lc appleetcode.cn id3271 langcpp** [3271] 哈希分割字符串*/// lc codestart class Solution { public:string stringHash(string s, int k){…

适用于 Windows 的 Citrix Workspace 中发现两项权限提升

在适用于 Windows 的 Citrix Workspace 应用程序中发现了两个高严重性漏洞CVE-2024-7889 和 CVE-2024-7890。 这些漏洞影响当前版本的 2405 之前的版本以及 LTSR 的 2402 CU1 之前的版本。 Citrix 建议客户立即更新其安装&#xff0c;以减轻使用 Citrix Workspace 环境的用户…