1.堆的功能

1.插入一个数
2.求集合当中最小值
3.删除最小值
(1-3stl能做)
4.删除任意一个元素
5.修改任意一个元素

堆的两个重要性质:
堆是一棵完全二叉树
小根堆:每一个结点的值都小于等于 左右儿子

2.堆的存储

用数组存储,1号点是根节点,x的左儿子是2x,右儿子是2x+1
下标从1开始比较方便
ph中p是指针,h是堆

3.堆的函数

down(x),往下调整
up(x),往上调整
heap_swap,交换元素和映射

down和up操作

假设有一个堆是这样的

很显然结点3不满足堆的性质,这时我们对其进行down操作
先比较3、1、4谁更小,明显1更小,越小越优秀,于是我们把1拿上来,3放下去。

这时我们继续对结点3进行down操作,比较3、2、5的大小,2是最小的,于是交换2和3

这样down操作就完成了。
up操作同理,只不过是up操作的结点只需要与父亲结点比较就可以了。

5.堆的初始化

假设有三个元素:213,初始化时,三个结点都是独立的堆

首先,我们区n/2(n在这里是3)的元素,它的孩子结点是1和3,且1和3都是堆

然后我们对2进行down操作

这样,堆的初始化就完成了。

6.删除堆中最小的元素

先把堆中最后一个结点和根结点互换,然后删除最后一个结点,再对新的根结点进行down操作。

ACWING838 堆排序
输入一个长度为 n 的整数数列,从小到大输出前 m 小的数。

输入格式
第一行包含整数 n 和 m。

第二行包含 n 个整数,表示整数数列。

输出格式
共一行,包含 m 个整数,表示整数数列中前 m 小的数。

数据范围
1≤m≤n≤105,
1≤数列中元素≤109
输入样例:
5 3
4 5 1 3 2
输出样例:
1 2 3

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int h[N], sz, n, m;
void down(int u)
{int t = u;if(u * 2 <= sz && h[u * 2] < h[t])t = u * 2;if(u * 2 + 1 <= sz && h[u * 2 + 1] < h[t])t = u * 2 + 1;if(u != t){swap(h[u], h[t]);down(t);}
}
int main()
{ios::sync_with_stdio(false);cin.tie(0);cin >> n >> m;sz = n;for(int i = 1; i <= n; i++)cin >> h[i];for(int i = n / 2; i; i--)down(i);while(m--){cout << h[1] << ' ';h[1] = h[sz--];down(1);}return 0;
}

这道题主要注意初始化堆时要从n/2开始。因为要从满足以下性质的结点开始down:
1.左右儿子满足堆的性质。
2.下标最大(因为要往上遍历)
3.不是叶结点(叶节点一定满足堆的性质)

堆排序的时间复杂度是O(n*logn)

ACWING839 模拟堆
维护一个集合,初始时集合为空,支持如下几种操作:
“I x”,插入一个数x;
“PM”,输出当前集合中的最小值;
“DM”,删除当前集合中的最小值(数据保证此时的最小值唯一);
“D k”,删除第k个插入的数;
“C k x”,修改第k个插入的数,将其变为x;
现在要进行N次操作,对于所有第2个操作,输出当前集合的最小值。

输入格式
第一行包含整数N。

接下来N行,每行包含一个操作指令,操作指令为”I x”,”PM”,”DM”,”D k”或”C k x”中的一种。

输出格式
对于每个输出指令“PM”,输出一个结果,表示当前集合中的最小值。

每个结果占一行。

数据范围
1≤N≤105
−109≤x≤109
数据保证合法。

输入样例:
8
I -10
PM
I -10
D 1
C 2 8
I 6
PM
DM
输出样例:
-10
6

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int h[N], hp[N], ph[N], isz, sz, n;
void heap_swap(int u, int v)
{swap(h[u], h[v]);swap(hp[u], hp[v]);swap(ph[hp[v]], ph[hp[u]]);
}
void down(int u)
{int t = u;if(u * 2 <= sz && h[u * 2] < h[t])t = u * 2;if(u * 2 + 1 <= sz && h[u * 2 + 1] < h[t])t = u * 2 + 1;if(u != t){heap_swap(u, t);down(t);}
}
void up(int u)
{if(u / 2 && h[u / 2] > h[u]){heap_swap(u / 2, u);up(u / 2);}
}
int main()
{ios::sync_with_stdio(false);cin.tie(0);int k, x;string op;cin >> n;while(n--){cin >> op;if(op == "I"){cin >> x;sz++;isz++;h[sz] = x;hp[sz] = isz;ph[isz] = sz;down(sz);up(sz);}if(op == "PM")cout << h[1] << '\n';if(op == "DM"){heap_swap(1, sz);sz--;down(1);}if(op == "D"){cin >> k;int u = ph[k];heap_swap(u, sz);sz--;down(u);up(u);}if(op == "C"){cin >> k >> x;h[ph[k]] = x;down(ph[k]);up(ph[k]);}}return 0;
}

这里要注意两个新增加的数据结构:hp和ph数组。ph中p是指针,h是堆,hp同理。
ph[i]:存储第i个插入的数在堆中的下标
hp[i]:存储在堆中下标为i的数是第几个插入的

可以看出,hp和ph类似于反函数。
理解了这个,我们就能理解heap_swap的含义:交换堆下标为v和u的两个元素的所有映射——h,hp,ph。由于这三个映射互不干扰,所以交换的顺序任意。

然后就是注意down和up的参数,如果是参数是ph,并且之前要用到heap_swap操作的话,那么一定要用临时变量把ph存起来,否则ph会变,就背离了编程者的初衷。

堆(基本介绍,代码实现,以及例题)相关推荐

  1. 数据结构之堆:堆的介绍与python实现——12

    堆的简单实现与代码实现 堆的定义 在定义堆(heap)之前,先回顾一下完全二叉树的定义: 完全二叉树:除了最后一层的结点有可能没有达到最大值外,其它层的结点值都达到最大值,此外最后一层的叶子结点会尽可 ...

  2. MATLAB 画三维长方体 介绍+代码

    MATLAB 画三维长方体 介绍+代码 在做机械臂三维避障仿真时可能用到对空间障碍物进行描述,一般用长方体,圆柱体等描述,以下是两种画长方体的程序,第一种是指定长方体的八个顶点坐标,第二种是指定长方体 ...

  3. 旋转数组的最小数字+堆排介绍19.9.14

    题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个 ...

  4. java 二叉堆_二叉堆的介绍和Java实现

    一.堆和二叉堆 堆,英文名称Heap,所谓二叉堆(也有直接称二叉堆为堆的),本质上是一个完全二叉树,前面也提到过,如果树接近于完全二叉树或者满二叉树,采用顺序存储代价会小一点,因此常见的二叉堆均是顺序 ...

  5. 十九.激光和惯导LIO-SLAM框架学习之项目工程代码介绍---代码框架和一些文件解释

    专栏系列文章如下: 一:Tixiao Shan最新力作LVI-SAM(Lio-SAM+Vins-Mono),基于视觉-激光-惯导里程计的SLAM框架,环境搭建和跑通过程_goldqiu的博客-CSDN ...

  6. 小蚂蚁学习数据结构(16)——串的堆分配储存代码演示

    2019独角兽企业重金招聘Python工程师标准>>> 根据对书上伪代码的理解,编写了这么一段堆分配储存的程序,反正运行着没有什么问题,看看网上其他人的代码,具体细节上有所不同外,思 ...

  7. 【介绍+代码实现】使用GradualWarmupScheduler进行学习率预热

    找了一晚上warmup资料,有用的很少,基本都是互相转载,要不就是讲的很空泛,代码没有可使用的价值.但是最后我还是解决了,于是写一个warmup教程造福大家,这里抛砖引玉了. 一.介绍GradualW ...

  8. Web中html个人介绍代码,web开发工程师自我介绍示例

    web开发工程师自我介绍示例 Web前端开发工程师,主要职责是利用(X)HTML/CSS/JavaScript/Flash等各种Web技术进行客户端产品的开发.小编整理了web开发工程师自我介绍示例, ...

  9. C++栈和堆原理介绍

    http://www.programfan.com/blog/article.asp?id=27508 C++应用中内存分为2部分,一部分是栈(stack,也称堆栈),另一部分是堆(heap). 栈: ...

  10. JVM堆内存介绍、垃圾收集算法、垃圾回收器汇总

    目录 1. JAVA堆内存是如何划分的 1.1 为什么移除永久代? 1.2 分代概念 1.3 为什么分代? 1.4 为什么survivor分为两块相等大小的幸存空间? 1.5 JVM堆内存常用参数 2 ...

最新文章

  1. TransCenter解读
  2. centos 卸载_CentOS「linux」学习笔记12:磁盘管理、分区挂载卸载操作
  3. 前台用js、jquery出现错误很多是由于IE缓存
  4. nginx fastcgi php-fpm的关系梳理
  5. pxe安装系统 ip获取错误_聊聊PXE的那点东西
  6. Elasticsearch 8.x 正式发布!
  7. 精雕软件怎么把图片转成灰度图_精雕软件怎样保存bmp
  8. 计算机办公软件海报,word知识面制作一个图文并茂的宣传海报
  9. SQL数据库学习总结(一)
  10. FPS游戏中的喷漆效果原理
  11. 亮道剧学铭:激光雷达系统量产上车没那么容易
  12. 新手学习Django的十条注意点
  13. 【书单】100部世界名著
  14. php检测wifi,WFilter插件 - 随身wifi和私接路由检测
  15. 147. Python语言 的 Flask框架项目前导 之 Flask数据库 第三章 :SQLAlchemy-ORM 介绍
  16. JavaScript循环对象拿到键和值
  17. 基于caffe在已有模型上进行微调finetune
  18. 2022CFA一级二级三级视频网课资源
  19. 硬盘累计通电时间存储在_在灾难期间保持通电
  20. 5G工业路由器在AGV小车的应用

热门文章

  1. Java RMI原理与使用
  2. jQuery 前后端分离项目总结
  3. 总结之:CentOS 6.5 rsync+inotify实现数据实时同步备份
  4. TP-Link C2和C20i产品出现命令注入、DoS等多个漏洞 绿盟科技发布安全威胁通告
  5. [BZOJ 4403]序列统计(Lucas定理)
  6. ci源码解析之CodeIgniter.php
  7. mac/linux终端光标的快捷键操作
  8. 在阿里云上安装MongoDB,并且远程连接
  9. 【SpringMVC】@Controller 和 @RestController 区别
  10. mysql配置my.cnf文件,以及参数优化提升性能