当前位置: 首页 > news >正文

数据结构系列之堆


前言

堆是一种比较重要的数据结构,可以解决Top- K 问题,它也是优先级队列priority_queue的底层原理.


一、什么是堆????

堆本质是一颗二叉树,并且是一棵完全二叉树 ! ! ! ! (其结点编号与相同深度的满二叉树对应位置一致)其中又分为大根堆和小根堆,大根堆—顾名思义:根比左孩子和右孩子的节点值都要大,小根堆相反.下面默认讲解的都是大根堆,因为堆的这个性质,根节点就是最大的节点.同时在每一颗子树中根节点都是最大的,由于这个性质,之后的排序算法之一就有一个堆排序(排序中讲).
对于下标:假如根节点的下标是i,左孩子的下标是2 * i + 1,右孩子的下标是2 * i + 2,孩子的节点的下标是i,父亲就是(i - 1) / 2
大根堆:
在这里插入图片描述

二、堆的操作

建堆 (大堆)

给你一组数字,怎么建堆? ? ? 核心操作: 从第一个不为叶子的节点倒着向下调整,调整到根节点为止,什么是向下调整? 堆的最核心条件是什么? ? ? 父节点比子节点要大!所以,向下调整的思想就是:先找出左右孩子中比较大的那个,如果这个节点比父节点要大,就交换,然后继续往下走! 否则直接break,一直调整到child >= n为止。
怎么找到第一个不为叶子的节点? ? ?
由于是完全二叉树,最后一个节点的父亲就一定是第一个不为叶子的节点,一共n个元素,最后一个节点的下标: n - 1 所以 这个节点的下标就是(n - 1 - 1) / 2
比如拿1 5 3 8 7 6来建堆

在这里插入图片描述

向下调整代码实现

void downAdjust(int* 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[parent] > a[child]){Swap(&a[parent], &a[child]);parent = child;child = parent * 2 + 1;}else{break;}}

建堆代码实现

void HeapInitArray(HP* php, int* a, int n)
{assert(php);php->a = (int*)malloc(sizeof(int) * n);if (php->a == NULL){perror("malloc");return;}php->capacity = n;php->size = n;for (int i = (n - 2) / 2; i >= 0; i--){downAdjust(php->a, php->size, i);}
}

插入

push进去数据,向上调整即可,什么是向上调整,很好理解,向下调整反过来即可,从该节点往上比较,比父亲大就交换,然后继续向上,否则直接break;
这里不画图了,很好理解。

向上调整代码

void upAdjust(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; }}
}

插入代码

这里如果用容器适配器就简单的多了,调用一下vector的push_back()即可,用C实现的就是和顺序表一样的插入逻辑

void HeapPush(HP* php, int x)
{assert(php);if (php->size == php->capacity){int* tmp = (int*)realloc(php->a, sizeof(int) * php->capacity * 2);if (tmp == NULL){perror("realloc");return ;}php->a = tmp;php->capacity *= 2;}php->a[php->size] = x;php->size++;upAdjust(php->a,php->size - 1);
}

删除

删除操作指的是删除堆顶,直接删除合适吗???当然不合适,一删除所有的关系全都乱了,所以这里我们采用交换删除法,将堆顶和最后一个元素交换,出掉,然后向下调整堆顶。

删除代码

void HeapPop(HP* php)
{assert(php);assert(!HeapEmpty(php));Swap(&php->a[0], &php->a[php->size-1]);  //不取地址就去传引用php->size--;downAdjust(php->a,php->size, 0);
}

三、时间复杂度分析

向下调整建堆的时间复杂度是O(N),我在优先级队列中已经讲了
个人博客

push和pop没啥说的,最多调整高度次,也就是log(N)

四、堆的应用

1.堆排序
这个想在排序算法中更新,这块就先停一下

2.Top-K问题
我在优先级队列里面也提到了
个人博客


总结

下次更新树

http://www.dtcms.com/a/482975.html

相关文章:

  • MySQL索引原理
  • 扁平化网站源码云服务器最便宜
  • 一个网站的成功深圳市深企在线技术开发有限公司
  • Python学习-----小游戏之人生重开模拟器(普通版)
  • 上海网站建设的网html网站系统
  • 理解AUROC,AP,F1-scroe,PRO
  • php做网站安全性wordpress 网银
  • 教程上新|重新定义下一代 OCR:IBM 最新开源 Granite-docling-258M,实现端到端的「结构+内容」统一理解
  • 网络原理 -- HTTP
  • 县级门户网站建设的报告网页游戏网站排名
  • 快速创建无线AP热点
  • CSS级联层样式权重和优先级
  • 免费搭建私人网站修改wordpress后台文字
  • 站内推广的方法网络整合营销传播
  • 国际网站建设的目的网站建设预算知乎
  • 瀚海微SD NAND/TF卡:赋能全场景数据存储,定义高效安全新基准
  • 怎样安全地开启MySQL远程管理权限?
  • 建设局网站查询个人信息wordpress首页文章显示固定分类
  • 网站建设多少钱实惠湘潭磐石网络企业网站建设的目的是什么
  • 知微传感Dkam系列3D相机SDK例程篇:Python设置相机触发模式
  • Java 故障分析与性能调优命令详解(含案例)
  • 【Pytorch】激活函数 Loss 梯度 超详细文本笔记
  • 不同材质金冠钳的力学性能及其对修复体就位影响研究
  • vs2015做网站的后端个人怎么做百度竞价
  • 微信小程序入门学习教程,从入门到精通,项目实战:美妆商城小程序 —— 知识点详解与案例代码 (18)
  • 微信小程序添加水印功能
  • 02_ES索引规范kibana
  • 购物网站建设模板图片价格低的跑车
  • LeetCode hot100:049 字母异位词分组:两种解法的深度解析
  • 网站建设业务前景政务信息网站建设制度