C语言数据结构堆排序、向上调整和向下调整的时间复杂度的计算、TopK问题等的介绍

文章目录

  • 前言
  • 一、堆排序
    • 1. 排升序
      • (1). 建堆
      • (2). 排序
    • 2. 拍降序
      • (1). 建堆
      • (2). 排序
  • 二、建堆时间复杂度的计算
    • 1. 向上调整时间复杂度
    • 2. 向下调整时间复杂度
  • 三、TopK问题
  • 总结


前言

C语言数据结构堆排序、向上调整和向下调整的时间复杂度的计算、TopK问题等的介绍


一、堆排序

排列一个一维数组,可以通过两个步骤进行排序。

  1. 建堆(大根堆或小根堆)
  2. 堆排序(通过向下或者向上调整排序)’

需要注意的是 堆排序排升序则建大堆,排降序则建小堆。

1. 排升序

(1). 建堆

这里建堆采用向下调整建堆,因为向上调整建堆的时间复杂度比向下调整建堆的时间复杂度大。可参考二。

  • 向下调整建堆,从最后一个叶子节点的父节点开始调整。
// 向下调整 按大根堆调整
void AdjustDown(HPDataType* a, int n ,int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		// 判断左右子树的根谁大 并防止越界
		if (child+ 1 < n && a[child] < a[child + 1])
		{
			child++;
		}

		if (a[child] > a[parent])
		{
			Swap(&a[parent], &a[child]);

			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}

	}
}

// 排升序 建大堆
void HeapSort(int* arr, int n)
{
	int i = 0;
	// 建堆---向下调整建堆
	for (i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(arr, n, i);
	}
}
  • (n-1)是找到最后一个叶子节点,(n-1-1)/2找到最后一个叶子节点的双亲节点,然后向下调整。

(2). 排序

  • 排序的思想:
    和删除堆顶的元素的思想一样。
  1. 已经建好了大堆,所以先交换根元素和最后一个叶子节点元素。此时最后一个叶子节点是最大值。
  2. 将此时除了最后一个叶子节点元素看成一个堆,并将此时的根元素向下调整。
  3. 再继续交换根元素和此时最后一个叶子结点元素,重复以上过程。即可达到排序效果。
// 排升序 建大堆
void HeapSort(int* arr, int n)
{
	int i = 0;
	// 建堆---向下调整建堆
	for (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--;
	}
}

int main()
{
	int arr[10] = { 2,3,1,9,5,7,8,6,4, 0 };
	
	HeapSort(arr, 10);

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	return 0;
}

效果如下:
在这里插入图片描述

2. 拍降序

(1). 建堆

  • 排降序,建小堆
  • 向下调整建小堆,向下调整的时间复杂度比向上调整时间复杂度低
// 向下调整 按小根堆调整
void AdjustDown(HPDataType* a, int n ,int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		// 判断左右子树的根谁小 并防止越界
		if (child+ 1 < n && a[child] > a[child + 1])
		{
			child++;
		}
		
		if (a[child] < a[parent])
		{
			Swap(&a[parent], &a[child]);

			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}

	}
}

// 拍降序,建小堆
void HeapSort(int* arr, int n)
{
	int i = 0;
	for (i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(arr, n, i);
	}
}

(2). 排序

  • 排序的思想:
    和删除堆顶的元素的思想一样。
  1. 已经建好了小堆,所以先交换根元素和最后一个叶子节点元素。此时最后一个叶子节点是最小值。
  2. 将此时除了最后一个叶子节点元素看成一个堆,并将此时的根元素向下调整。
  3. 再继续交换根元素和此时最后一个叶子结点元素,重复以上过程。即可达到排序效果。
// 拍降序,建小堆
void HeapSort(int* arr, int n)
{
	int i = 0;
	// 建堆---- 向下调整建堆
	for (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--;
	}


}

int main()
{
	int arr[10] = { 2,3,1,9,5,7,8,6,4, 0 };
	
	HeapSort(arr, 10);

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	return 0;
}

效果如下:
在这里插入图片描述

注意拍升序和拍降序的向下调整函数是不一样的

二、建堆时间复杂度的计算

  • 建堆事实上是模拟堆中插入数据,并向上或向下调整。
  • 所以建堆时间复杂度的计算本质上是向上或者向下调整的时间复杂度

注意: 堆是完全二叉树,这里用满二叉树来近似计算,因为时间复杂度计算的是量级,多或少节点不影响。

1. 向上调整时间复杂度

见图示:
1.
在这里插入图片描述

在这里插入图片描述

2. 向下调整时间复杂度

见图示:
1.
在这里插入图片描述

在这里插入图片描述

三、TopK问题

在非常大的数字中找到前K个

  • 由于没有数据,先随机生成10000个数据写入文件中
  • 然后建K个数据的小堆
  • 剩余n-k个数据依次与小堆根元素比较,若大于根元素则入堆,并向下调整,若不大于根元素,则继续找下一个,知道文件读完。
void PrintfTopK(const char* file, int k)
{
	int* topk = (int*)malloc(sizeof(int)* k);
	if (topk == NULL)
	{
		perror("PrintfTopK malloc");
		return;
	}

	// 以读的形式打开文件
	FILE* pfout = fopen(file, "r");
	if (pfout == NULL)
	{
		perror("PrintfTopK fopen");
		return;
	}

	int i = 0;
	// 读出前K个数
	for (i = 0; i < k; i++)
	{
		fscanf(pfout, "%d", &topk[i]);
	}

	// 建堆
	for (i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(topk, k, i);
	}

	// 剩余n - k 个数分别于根元素比较
	int val = 0;
	int ret = fscanf(pfout, "%d", &val);
	while (ret != EOF)
	{
		if (val > topk[0])
		{
			topk[0] = val;
			AdjustDown(topk, k, 0);
		}

		ret = fscanf(pfout, "%d", &val);
	}


	for (i = 0; i < k; i++)
	{
		printf("%d ", topk[i]);
	}

	free(topk);
	fclose(pfout);
}



void CreateNData()
{
	int n = 10000;
	const char* file = "data.txt";
	FILE* pfin = fopen(file, "w");

	if (pfin == NULL)
	{
		perror("TestTopK fopen");
		return;
	}

	int i = 0;
	for (i = 0; i < n; i++)
	{
		int x = rand() % 10000;
		fprintf(pfin, "%d\n", x);
	}
	
	fclose(pfin);
}

int main()
{
	srand((unsigned int)time(NULL));
	CreateNData();
	PrintfTopK("data.txt", 10);

	return 0;
}
  • 其中的向下调整都是按小根堆向下调整。可参考一、二内容

效果如下:
在这里插入图片描述


总结

C语言数据结构堆排序、向上调整和向下调整的时间复杂度的计算、TopK问题等的介绍

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

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

相关文章

数据库设计实例---学习数据库最重要的应用之一

一、引言【可忽略】 在学习“数据库系统概述”这门课程时&#xff0c;我一直很好奇&#xff0c;这样一门必修课&#xff0c;究竟教会了我什么呢&#xff1f; 由于下课后&#xff0c;&#xff0c;没有拓展自己的眼界&#xff0c;上课时又局限于课堂上老师的讲课水平&#xff0c;…

Java+mysql酒店管理系统

1&#xff0e;引言 1.1编写的目的 本文档为酒店管理系统需求分析报告&#xff0c;为酒店管理系统的设计的主要依据&#xff0c;主要针对酒店管理系统的概要设计和详细设计人员&#xff0c;作为项目验收的主要依据。 1.2背景 本软件全称为阳光酒店管理系统。 1.3 参考资料 …

Windows和Linux系统部署Docker(2)

目录 一、Linux系统部署docker 前置环境&#xff1a; 1.安装需要的软件包&#xff0c; yum-util 提供yum-config-manager功能 2.添加阿里云 docker-ce 仓库 3.安装docker软件包 4.启动 docker并设置开机自启 5.查看版本&#xff1a; 二、windows系统部署docker 1.查看…

.NET 直连SAP HANA数据库

前言 上个项目碰到的需求&#xff0c;IT部门要求直连SAP的HANA数据库&#xff0c;以只读的权限读取SAP部门开发的CDS视图&#xff0c;是个有点复杂的工程&#xff0c;需要从成品一直往前追溯到原材料的产地&#xff0c;和交货单、工单、采购订单有相当程度上的关联 IT部门要求…

代码随想录算法训练营第五十四天||392.判断子序列、115.不同的子序列

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、392.判断子序列 思路 二、115.不同的子序列 思路 一、392.判断子序列 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是…

Money Trees

思路分析: 利用双指针 l1始终作为起点,ri,不断更新终点 #include<iostream> #include<cstring> #include<string> #include<algorithm> #define int long long using namespace std; int w[2000005],h[2000005],s[2000005]; int t,n,m,l,r; signed m…

信息学奥赛初赛天天练-15-阅读程序-深入解析二进制原码、反码、补码,位运算技巧,以及lowbit的神奇应用

更多资源请关注纽扣编程微信公众号 1 2021 CSP-J 阅读程序1 阅读程序&#xff08;程序输入不超过数组或字符串定义的范围&#xff1b;判断题正确填 √&#xff0c;错误填&#xff1b;除特 殊说明外&#xff0c;判断题 1.5 分&#xff0c;选择题 3 分&#xff09; 源码 #in…

什么是访问控制漏洞

什么是AC Bugs&#xff1f; 实验室 Vertical privilege escalation 仅通过隐藏目录/判断参数来权限控制是不安全的&#xff08;爆破url/爬虫/robots.txt/Fuzz/jsfinder&#xff09; Unprotected functionality 访问robots.txt 得到隐藏目录&#xff0c;访问目录 &#xff0c;…

使用Jmeter进行性能测试的基本操作方法

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

长难句打卡5.29

Today, professors routinely treat the progressive interpretation of history and progressive public policy as the proper subject of study while portraying conservative or classical liberal ideas — such as free markets and self-reliance — as falling outsid…

【SPSS】基于因子分析法对水果茶调查问卷进行分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

No input file specified.(‘.user.ini’文件问题宝塔复制到本地,其他情况可跳过)

症状 病因 一般是宝塔直接copy到本地的情况。 宝塔面板中的.user.ini文件是一个重要的配置文件&#xff0c;它主要用于配置PHP运行环境和网站环境。以下是.user.ini文件的主要作用和操作建议&#xff1a; 防止跨目录访问和文件跨目录读取。这是.user.ini文件的主要作用之一&a…

采用Java+ SpringBoot+ IntelliJ+idea开发的ADR药物不良反应监测系统源码

采用Java SpringBoot IntelliJidea开发的ADR药物不良反应监测系统源码 ADR药物不良反应监测系统有哪些应用场景&#xff1f; ADR药物不良反应监测系统有哪些应用场景&#xff1f; ADR药物不良反应监测系统具有广泛的应用场景&#xff0c;以下是一些主要的应用场景&#xff1a…

AVL树的模拟实现

我们上期提到了二叉搜索树&#xff0c;只是简单的讲了一下原理&#xff0c;那么今天我们就讲一下AVL树。 目录 AVL树的概念AVL树的实现AVL树的架构insert插入引用pair对象引进parent指针仅插入数据调节平衡因子情况1&#xff1a;插入在父亲的右边&#xff0c;父亲的平衡因子后…

如何应对Android面试官 -> 玩转 Fragment

前言 本章主要讲解下 Framgent 的核心原理&#xff1b; 基础用法 线上基础用法&#xff0c;其他的可以自行百度 FragmentManager manager getSupportFragmentManager(); FragmentTransaction transaction manager.beginTransaction(); transaction.add(R.id.contentlayout,…

100个投资者99个选择使用这款EA,WeTrade发现1个事实

为什么100个投资者会有99个选择使用这款EA&#xff0c;是因为这款EA能提供两个版本吗?是因为能控制风险吗?都不是&#xff0c;WeTrade发现1个事实才是这么多投资者选择的原因&#xff0c;那就是能实现100%的盈利率。 我们都知道外汇狙击手EA提供两种版本&#xff0c;分别是标…

2018 年山东省职业院校技能大赛高职组“信息安全管理与评估”赛项任务书

2018年山东省职业院校技能大赛高职组 “信息安全管理与评估”赛项任务书 赛项时间 8:30-13:00&#xff0c;共计4小时30分钟&#xff0c;含赛题发放、收卷时间。 赛项信息 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段 平台搭建与安全设备配置防护 …

云原生网关 MSE-Higress

云原生网关 MSE-Higress 什么是云原生网关MSEMSE测评产品文档产品能力产品控制台 MSE与其他网关 什么是云原生网关MSE 在体验云原生网关 MSE-Higress功能之前&#xff0c;先了解一下什么是云原生网关 MSE&#xff0c;简单的说就是MSE就是遵循开源 Ingress/Gateway API 标准的下…

kubernetes(Jenkins、kubernetes核心、K8s实战-KubeSphere、)

文章目录 1. Jenkins1.1. 概述1.1.1. 简单部署1.1.2. 自动化部署1.1.3. DevOps概述1.1.4. CI/CD概述 1.2. jenkins介绍及安装1.2.1. 安装1.2.2. 解锁jenkins1.2.3. 安装推荐插件1.2.4. 创建管理员用户1.2.5. 升级jenkins版本1.2.6. 安装额外插件blue ocean1.2.7. jenkins界面说…