重生之“我打数据结构,真的假的?”--5.堆(无习题)

news2024/11/12 17:01:43

1.堆的概念与结构

如果有⼀个关键码的集合 ,把它的所有元素按完全⼆叉树的顺序存储⽅ 式存储,在⼀个⼀维数组中,并满⾜: ( 且 ), i = 0、1、2... ,则称为⼩堆(或⼤堆)。将根结点最⼤的堆叫做最⼤堆或⼤根堆根结点最⼩的堆 叫做最⼩堆或⼩根堆

2.堆的性质

• 堆中某个结点的值总是不⼤于或不⼩于其⽗结点的值;

• 堆总是⼀棵完全⼆叉树

3.堆的实现

3.1初始化及基础功能

typedef struct heap
{
	int* a;
	int size;
	int capacity;
}HP;

void heapinit(HP* php)
{
	assert(php);
	php->a = NULL;
	php->size = 0;
	php->capacity = 0;
}                    //初始化

void swap(int* p1, int* p2)
{
	int t = 0;
	t = *p1;
	*p1 = *p2;
	 *p2 = t;
}                   //交换函数

void heappush(HP* php, int data)
{
	if (php->size == php->capacity)   //如果内存空间满了
	{
		int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;                          //内存空间和元素数量一样》》》》》1.内存空间为0,令内存大小为4, 2.内存空间满了,扩容至两倍大
		int* tmp = (int*)realloc(php->a, newcapacity * sizeof(int));                           //开辟内存空间记得加sizeof(sldatatype) 
		php->a = tmp;                                                                          //开辟内存空间赋给a指针
		php->capacity = newcapacity;                                                           //设置新的容量
	}
	php->a[php->size] = data;
	php->size++;
	adjustup(php->a, php->size - 1);
}

void heappop(HP* php)
{
	swap(&php->a[0],&php->a[php->size - 1]);
	php->size--;
	adjustdown(php->a,php->size-1,0);//首尾互换!!!!!!,可以保证根节点以下的二叉树均不被改变(即排好序),只需由新的根节点从上往下排序交换一轮
}

bool heapempty(HP* php)
{
	return php->size == 0;
}                               //判断是否为空

int heaptop(HP* php)
{
	assert(php);
	return php->a[0];
}                               //取根节点

3.2 向上调整算法

向上调整算法

• 先将元素插⼊到堆的末尾,即最后⼀个孩⼦之后

• 插⼊之后如果堆的性质遭到破坏,将新插⼊结点顺着其双双亲往上调整到合适位置即可

(要求插入前必须是堆)!!!!!!

void adjustup(int* a, int child)         //向上调整法    //上方必须是堆
{
	int parent = (child-1)/2;
	while (child>0)
	{
		if (a[parent]<=a[child])        //小堆为>=,大堆为<=
		{
			swap(&a[parent],&a[child]);
			child = parent;
			parent = (child - 1)/2;
		}
		else
		{
			break;
		}
	}
}

3.3 向下调整算法

向下调整算法

• 将堆顶元素与堆中最后⼀个元素进⾏交换

• 删除堆中最后⼀个元素

• 将堆顶元素向下调整到满⾜堆特性为⽌

!!!!!!向下调整算法有⼀个前提:左右⼦树必须是⼀个堆,才能调整。

 

void adjustdown(int* a,int n, int parent)     //向下调整法,!!!!!!(仅适用于根结点两端都是大堆或小堆)
{
	int child = 2 * parent + 1;
	while (child<=n)                   //
	{
		if (child + 1<=n && a[child + 1] > a[child])      //   child+1>n可以推出child==n,所以只有左孩子
		{
			child++;                          //选出左右孩子中最大的一个‘>’,最小的为'<'
		}
			if (a[parent]<=a[child])        //大堆为“<=”,小堆为“>=”
			{
				swap(&a[parent], &a[child]);
				parent = child;
				child = 2 * parent + 1;     //每次都先找左孩子
			}
			else
			{
				break;
			}
	}
}

 

4.堆排序 

int main()
{
	int a[] = { 65,100,70,32,50,35 };
	int i;
	int n = sizeof(a) / sizeof(a[0]);
	int flag = n;
	for (i = 1; i < sizeof(a) / sizeof(a[0]); i++)     //i从1开始,因为只有一个元素时可以视作堆
	{
		adjustup(a, i);
	}                    //升序排序前的第一步,建立大堆,i从1开始,因为i=0时可视作堆,从1开始向上调整
	                   //记住,只是建好了堆,堆不代表直接打印出来是有序的!!!!!!!!!还需要调整


	while (n>0)          //上文所说的调整,因为是大堆,所以root一定是最大的
	{
		swap(&a[0],&a[n-1]);//将最大的换到tail
		n--;                //不再关注最大的tail
		adjustdown(a,n-1, 0);//排除tail后重新建立大堆,选择从根开始的向下调整最合适(交换后,根的左右两边都是堆,只是根变了),让第二大的变为root,循环
	}                  


	for (i = 0; i <= flag - 1; i++)
	printf("%d ",a[i]);
	return 0;
}

5.实际问题解决 ——topK问题

TOP-K问题:即求数据结合中前K个最⼤的元素或者最⼩的元素,⼀般情况下数据量都⽐较⼤。 ⽐如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。 对于Top-K问题,能想到的最简单直接的⽅式就是排序,但是:如果数据量⾮常⼤,排序就不太可取了 (可能数据都不能⼀下⼦全部加载到内存中)。最佳的⽅式就是⽤堆来解决,基本思路如下:

1)⽤数据集合中前K个元素来建堆

前k个最⼤的元素,则建⼩堆

前k个最⼩的元素,则建⼤堆

2)⽤剩余的N-K个元素依次与堆顶元素来⽐较,不满⾜则替换堆顶元素

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

void CreateNDate()
{
// 造数据
   int n = 100000;
   srand(time(0));
   const char* file = "data.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 topk()
{
  printf("请输⼊k:>");
  int k = 0;
  scanf("%d", &k);
  const char* file = "data.txt";
  FILE* fout = fopen(file, "r");
  if (fout == NULL)
  {
   perror("fopen error");
   return;
  }
  int val = 0;
  int* minheap = (int*)malloc(sizeof(int) * k);
  if (minheap == NULL)
   {
    perror("malloc error");
    return;
   }
  for (int i = 0; i < k; i++)
  {
    fscanf(fout, "%d", &minheap[i]);
  }

  // 建k个数据的⼩堆
   for (int i = (k - 1 - 1) / 2; i >= 0; i--)
   {
    AdjustDown(minheap, k, i);
   }

   int x = 0;
   while (fscanf(fout, "%d", &x) != EOF)
  {
    // 读取剩余数据,⽐堆顶的值⼤,就替换他进堆
    if (x > minheap[0])
     {
      minheap[0] = x;
      AdjustDown(minheap, k, 0);
     }
}

    for (int i = 0; i < k; i++)
    {
     printf("%d ", minheap[i]);
     }
     fclose(fout);
}







 

 

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

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

相关文章

逻辑处理模块:FPGA复旦微JFM7VX690T36+网络加速器:雄立XC13080-500C

逻辑处理模块通常是指在计算机系统、软件应用或电子设备中负责执行逻辑运算和决策过程的组件。 在不同的领域和技术中&#xff0c;逻辑处理模块可能有不同的实现方式和名称&#xff0c;但它们的核心功能都是基于输入数据进行逻辑判断和处理&#xff0c;并产生相应的输出结果。下…

GO-学习-03-基本数据类型

数据类型&#xff1a;基本数据类型和复合数据类型 基本数据类型&#xff1a;整型、浮点型、布尔型、字符串 复合数据类型&#xff1a;数组、切片、结构体、函数、map、通道&#xff08;channel&#xff09;、接口 整型&#xff1a; package main import "fmt" im…

react-native从入门到实战系列教程一环境安装篇

充分阅读官网的环境配置指南&#xff0c;严格按照他的指导作业&#xff0c;不然你一直只能在web或沙箱环境下玩玩 极快的网络和科学上网&#xff0c;必备其中的一个较好的心理忍受能力&#xff0c;因为上面一点就可以让你放弃坚持不懈&#xff0c;努力尝试 成功效果 三大件 …

「Unity3D」场景中的距离单位Unit与相关设置PixelsToUnits、PixelsPerUnit

GameObject在场景的位置Position&#xff0c;并没有明确是什么具体单位——如&#xff1a;Transform的x、y、z&#xff0c;或RectTransform的PosX、PosY、PosZ。而RectTransform在面板上显示的Width和Height&#xff0c;也没有具体单位&#xff0c;其实并不是像素。 事实上&am…

python+vue3+onlyoffice在线文档系统实战20240725笔记,首页开发

解决遗留问题 内容区域的高度没有生效&#xff0c;会随着菜单的高度自动变化。 解决方案&#xff1a;给侧边加上一个最小高度。 首页设计 另一种设计&#xff1a; 进来以后&#xff0c;是所有的文件夹和最近的文件。 有一张表格&#xff0c;类似于Windows目录详情&…

友盟U-APM——优秀的前端性能监控工具

在数字化转型浪潮的推动下,移动应用已成为企业连接用户、驱动业务增长的核心载体。然而,随着应用复杂度的日益提升,用户对于应用性能稳定性的期待也水涨船高。面对应用崩溃、卡顿、加载缓慢等频发问题,如何确保应用的流畅运行,成为产研团队亟待解决的关键挑战。在此背景下,友盟…

vite5-macos仿macOS网页osx管理系统|vue3+arcoDesign桌面os

基于vite5.xvue3arco-design原创自研网页版os管理框架ViteWebOS。 使用最新前端技术vite5vue3pinia2arcoDesignsortablejsecharts搭建网页pc版桌面os式后台管理系统解决方案。支持自定义桌面栅格布局引擎、可拖拽桌面图标、多屏分页管理、自定义桌面壁纸主题、毛玻璃虚化背景等…

【漏洞复现】E-Cology OA——WorkflowServiceXml——SQL注入

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 E-Cology OA协同商务系统是一款面向中大型组织的数字化办公产品…

LeNet卷积神经网络,手写数字识别

1. LeNet卷积神经网络的概念 先看看GPT的回答 有的资料中分层为 他们之间得差别就在于gpt的卷积层c5和上图中的全连接层1是同一种概念&#xff0c;因为该层使用的是5*5的卷积核&#xff0c;步长为一&#xff0c;根据公式可以算出输出的大小即是1X1的大小 训练参数是卷积核的大…

sentinel 服务流量控制 、熔断降级

1、什么是 sentinel,可以用来干什么 sentinel是用来在微服务系统中保护微服务对的作用,如何避免服务的雪崩、熔断、降级,说白了就是用来替换hystrix。 Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 官网:GitHub - alibaba/Se…

Python从0到100(四十三):数据库与Django ORM 精讲

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…

08 capture软件新建原理图 09 原理图添加元器件 10 原理图信号连通 11 原理图电源和地连通

08 capture软件新建原理图 && 09 原理图添加元器件 && 10 原理图信号连通 && 11 原理图电源和地连通 第一部分 08 capture软件新建原理图第二部分 09 原理图添加元器件第三部分 10 原理图信号连通第四部分 11 原理图电源和地连通 第一部分 08 capture软…

服务器重启了之后就卡在某个页面了,花屏,如何解决??

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

LC61----1374. 生成每种字符都是奇数个的字符串(字符串)---java版

1.题目 2.思路 &#xff08;1&#xff09;题目要生成每种字符是奇数个的字符串。 &#xff08;2&#xff09;所以直接用参数n%2来判断。 (3)返回的字符串必须只含小写英文字母。如果存在多个满足题目要求的字符串&#xff0c;则返回其中任意一个即可。 (4)感觉题目不是很规范哈…

云服务器部署vite前端项目

本篇博客将详述眨眼睛部署前端项目遇到的问题和解决方法 打包vite项目 输入指令会生成一个dist文件夹 npx vite build 如果我们使用liveServer打开这个html会发现报错 细看一下&#xff0c;是生成的路径都是以/开头&#xff0c;按理我们应该使用相对路径 当然它默认这么生成肯定…

lambda表达式,真题示例

Lambda表达式 它使代码更加简洁、易读&#xff0c;函数式编程增强了代码的表达力。常用于对集合的操作&#xff0c;如遍历、过滤、转换等。 Lambda表达式的形式&#xff1a; 参数&#xff0c; 箭头&#xff08;->) 以及一个表达式&#xff1a; (String first, String sec…

如何找到最快解析速度的DNS

如何找到最快解析速度的DNS DNS,即域名系统(Domain Name System),是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使用户更方便地访问互联网,而不用记住能够被机器直接读取的IP数串。 在浏览网页时,我们通常使用域名,而不是IP地址。当域名在…

虚拟机复制后网络不可用,报错“network.service - LSB: Bring up/down networking”

查询IP地址&#xff0c;eth33 没有显示IP地址 尝试重启&#xff0c;有报错&#xff0c;并且有提示&#xff0c;按照提示执行下看看 解决办法 chkconfig NetworkManager offsystemctl disable NetworkManager.serviceservice NetworkManager stopservice network restart 之后检…

堆(c++)

堆是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。 堆总是满足下列性质&#xff1a; 堆中某个节点的值总是不大于或不小于其父节点的值&#xff1b;堆总是一棵完全二叉树。 常见的堆有二叉堆、斐波那契堆等。 堆是非线性数据结构&#…

hugging face 使用教程———快速入门

概述 本篇存在的意义是快速介绍hugging face使用&#xff0c;梳理主要部件&#xff0c;梳理易混淆概念。原因是&#xff1a;目前hugging face的使用&#xff0c;官方放在了3个地方&#xff08;参考链接部分&#xff09;&#xff1a;使用文档、NLP教程、Transformers git的readm…