5分钟速成堆

FBI⚠WARNING

本文要素过多

吐槽

堆是我迄今为止学过最简单的数据结构

我还没学会最小生成树、最短路时就学会了

堆实用高效,值得推荐

(如果你看完了这篇文章还不会,你可以直接Copy,慢慢理解)

了解什么是堆

堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。————摘自(没人看得懂的)度娘

  

堆的特性?
堆中某个节点的值总是不大于(大根堆)或不小于(小根堆)其父节点的值;
堆总是一棵完全二叉树。
堆的作用?
堆支持查找最值的操作。
堆的实现
堆有5种操作,上移、下移、插入、删除、建堆。

(本文采用迭代法,如果你难以理解,可以使用递归法)

上移

若比父节点大/小,则与父节点交换(上移)

 //我们以小根堆为例:
void up(int x){//把x这个位置上移
while (x>&&c[x]<c[x/]){
swap(x,x/);//交换
x/=;//节点变化
}
return;
}

下移

若比子节点大/小,则与子节点交换(下移)

//我们以小根堆为例:
void down(int x){//把x这个位置下移
while (x*2<=cnt&&c[x]>c[x/2]||x*2+1<=cnt&&c[x]>=c[x*2+1]){
int y=x*2;
if (y+1<=cnt&&c[y]>c[y+1]) y++;//尽量选小的换
swap(x,y);//交换
x=y;//节点变化
}
return;
}

插入

元素会有变化,所以要用到插入

设cnt为堆元素总数,c为堆,则在c[++cnt]插入

但是此时堆不一定保持特性

所以进行上移

维护堆

void down(int x){//插入x
c[++cnt]=x;
up(cnt);
return;
}

  

删除

当我们要删除最值

就将堆顶弹出(显而易见)

但是特性不一定能保持

所以我们将堆底放到堆顶

再下移

void del(int x){//删除x
c[1]=c[cnt--];
down(1);
return;
}

建堆

无脑暴力:不断插入

O(NlogN)

for (int i=1;i<=n;i++){
scanf("%d",&x);
insert(x);
}

  

优化:处理一半,自然OK

O(N)

for (int i=1;i<=n;i++){
scanf("%d",&c[i]);
}
for (int i=n/2;i>0;i--)
down(i);

重中之重(c++福利)

c++有优先队列(堆)

可以直接调用函数

大家可以自学

例题

排序(经典堆排序)

code如下(pascal,code来自jzoj.net,a是堆,num是堆元素总数)

var
num,i,j,k,m,n,x,y:longint;
a:array[0..200001]of longint;
procedure up(x:longint);
var
i,sw:longint;
begin
while(a[x div 2]>a[x])and(x>1)do
begin
sw:=a[x div 2];
a[x div 2]:=a[x];
a[x]:=sw;
x:=x div 2;
end;
end;
procedure down(x:longint);
var
i,t:longint;
begin
while(2*x<=num)and(a[x]>a[2*x])or(2*x+1<=num)and(a[x]>=a[2*x+1]) do
begin
i:=2*x;
if(i+1<=num)and(a[i+1]<a[i]) then inc(i);
t:=a[x];
a[x]:=a[i];
a[i]:=t;
x:=i;
end;
end; begin
read(m);
for i:=1 to m do
begin
inc(num);read(a[num]);up(num);
end;
for i:=1 to m do
begin
writeln(a[1],' ');
a[1]:=a[num]; a[num]:=0;
dec(num);
down(1);
end;
end.

思路:首先建一个堆,然后每次取出堆顶并输出,然后删除堆顶

O(NlogN)

合并果子

一堆果子,有权值,每次合并,则权值为合并果子权值和,耗费体力相同

问体力消耗最小值

本题用贪心,每次将最小的两堆果子合并

用堆实现

弹出堆顶,维护之

再取堆顶,堆顶等于两次权值和

并且再次维护

经典贪心

code(code来自jzoj.net,heap是堆,heap_size是堆元素总数)

#include <cstdio>
using namespace std;
int heap_size,n;
int heap[30001];
void swap(int &a,int &b){int t=a;a=b;b=t;}
void put(int d){
int now,next;
heap[++heap_size]=d;
now=heap_size;
while(now>1){
next=now>>1;
if(heap[now]>=heap[next]) return;
swap(heap[now],heap[next]);
now=next;
}
}
int get(){
int now,next,res;
res=heap[1];
heap[1]=heap[heap_size--];
now=1;
while(now*2<=heap_size){
next=now*2;
if(next<heap_size&&heap[next+1]<heap[next]) next++;
if(heap[now]<=heap[next]) return res;
swap(heap[now],heap[next]);
now=next;
}
return res;
}
void work(){
int i,x,y,ans=0;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&x);
put(x);
}
for(i=1;i<n;i++){
x=get();
y=get();
ans+=x+y;
put(x+y);
}
printf("%d",ans);
}
int main(){
work();
return 0;
}

顺手点个赞

堆(c++)的更多相关文章

  1. Java 堆内存与栈内存异同(Java Heap Memory vs Stack Memory Difference)

    --reference Java Heap Memory vs Stack Memory Difference 在数据结构中,堆和栈可以说是两种最基础的数据结构,而Java中的栈内存空间和堆内存空间有 ...

  2. [数据结构]——堆(Heap)、堆排序和TopK

    堆(heap),是一种特殊的数据结构.之所以特殊,因为堆的形象化是一个棵完全二叉树,并且满足任意节点始终不大于(或者不小于)左右子节点(有别于二叉搜索树Binary Search Tree).其中,前 ...

  3. 《徐徐道来话Java》:PriorityQueue和最小堆

    在讲解PriorityQueue之前,需要先熟悉一个有序数据结构:最小堆. 最小堆是一种经过排序的完全二叉树,其中任一非终端节点数值均不大于其左孩子和右孩子节点的值. 可以得出结论,如果一棵二叉树满足 ...

  4. 计算机程序的思维逻辑 (47) - 堆和PriorityQueue的应用

    45节介绍了堆的概念和算法,上节介绍了Java中堆的实现类PriorityQueue,PriorityQueue除了用作优先级队列,还可以用来解决一些别的问题,45节提到了如下两个应用: 求前K个最大 ...

  5. JVM学习(2)——技术文章里常说的堆,栈,堆栈到底是什么,从os的角度总结

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: 堆栈是栈 JVM栈和本地方法栈划分 Java中的堆,栈和c/c++中的堆,栈 数据结构层面的堆,栈 os层面 ...

  6. 数据结构:优先队列 基于堆实现(python版)

    #!/usr/bin/env python # -*- coding:utf-8 -*- ''' Author: Minion-Xu ''' #异常类 class HeapPriQueueError( ...

  7. 数据结构:堆排序 (python版) 小顶堆实现从大到小排序 | 大顶堆实现从小到大排序

    #!/usr/bin/env python # -*- coding:utf-8 -*- ''' Author: Minion-Xu 小堆序实现从大到小排序,大堆序实现从小到大排序 重点的地方:小堆序 ...

  8. Java中堆内存和栈内存详解2

    Java中堆内存和栈内存详解   Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,ja ...

  9. AC日记——二叉堆练习3 codevs 3110

    3110 二叉堆练习3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 给定N(N≤500,000)和N个整 ...

  10. codevs 2879 堆的判断

    codevs 2879 堆的判断 http://codevs.cn/problem/2879/ 题目描述 Description 堆是一种常用的数据结构.二叉堆是一个特殊的二叉树,他的父亲节点比两个儿 ...

随机推荐

  1. 百炼OJ - 1007 - DNA排序

    题目链接:http://bailian.openjudge.cn/practice/1007 #include<stdio.h> #include<algorithm> usi ...

  2. 如和针对CPU时间百分比,Mem使用bytes,以及Network RecvBytes/SendBytes指标性能压测数据可视化

    设计思路:通过jmeter5.1压测获取cpu,Mem,Network的压测指标数据利用pandas+openpyxl进行数据可视化: 涉及添加jar包:下载地址:https://files.cnbl ...

  3. css 文本换行 文本溢出隐藏用省略号表示剩下内容

    正常文本的显示 <style> p{ width: 300px; box-shadow: 0 0 10px #ccc; padding: 0 20px; margin: 20px 100p ...

  4. MNIST数据集环境搭建

    由于换了电脑,ubuntu是重新下载的,因此记录一些相关数据集的搭建: 首先是data数据集,在第七讲中 我们需要建立data文件夹,并将数据集放进去 再就是model模型 我们应该新建一个model ...

  5. Bugku-CTF之这是一个神奇的登陆框

    Day32 这是一个神奇的登陆框 http://123.206.87.240:9001/sql/ flag格式flag{}  

  6. bugku 域名解析题 50

    什么是域名解析???? 首先我们在Windows上找到文件“C:\Windows\System32\drivers\etc\hosts” 然后找到host 双击用记事本打开然后填写上黄色区域上的东西 ...

  7. Crawlab-分布式爬虫管理系统

    一.简介 Crawlab 基于Celery的爬虫分布式爬虫管理平台,支持多种编程语言以及多种爬虫框架. Github: https://github.com/tikazyq/crawlab 参考资料 ...

  8. phpStudy的虚拟站点域名管理

    使用phpStudy在本地环境,使用虚拟域名访问本地站点. 步骤: 0x01  修改配置文件 打开站点域名管理 添加你本地站点的路径,第二域名可以不填,网站端口不填的话默认为80. 先点击新增,再点击 ...

  9. 专题一 Java基础语法

    小辨析: println 输出字符后,下一个输出的字符会换行展示 print 输出字符后,下一个输出字符不会会换展示 system.out.println()  空格 分支结构:if-else使用说明 ...

  10. Docker学习笔记(1):CentOS7安装Docker

    Docker是一个基于Go语言实现的开源应用容器引擎,通过对应用组件的封装.分发.部署.运行等生命周期的管理,使程序及其运行环境能够做到"一次封装,到处运行". Docker架构 ...