堆应用

2016.5.8 神奇的博客
我又回来啦

如果有人问我是怎么瘦下来的,我会告诉他:“得着肠胃炎学数据结构,效果真是要上天!”
今天更的是堆的学习心得;

(弱化版)给你一些数,有两种操作:

第一种:输入c i d
把第i个数换成d

第二种:输入q
找所有数中的最大

正当我傻了吧唧的用着log(n)的暴力,发现n是1000000,操作总数是10000的时候。。。所以说用暴力是绝对绝对不可以的啦!这时就选择了-------堆。

1

/      \

2        3

/   \       /   \

4     5      6    7

/  \    /  \    /   \     /   \

8   9 10 11 12 13 14 15

其实呢,我们只用最下面的一行来存储数据,那么上面的都是干什么的嘞?

15

/             \

11            15

/   \           /   \

6    11      15    3

/  \    /  \    /   \     /   \

6   2  7 11 8 15    3  0

(博主的树好丑。 [汗。。。])把我的数据放进去。可以看出每个节点就是左子和右子的两个数中的最大值。也就是说如果你取所有数的最大值只是log(1),
log(1)!!!只需要把最上方的取出来即可。

如果是修改呢?其实说这个方法和暴力是相反的,暴力就是修改容易取值难,但是堆是取值容易修改难。

15

/             \

11            15

/   \           /   \

6    11      15    3

/  \    /  \    /   \     /   \

6   2  7 11 8 15    3  0

假设我们修改的是3,修改成19的话,

15

/             \

11            15

/   \           /   \

6    11      15       3

/  \    /  \    /   \     /   \

6   2  7 11 8 15  19   0

这是不可能的,因为你需要把上面所有的区间跟它有关的全部修改。也就是说要递推上去,修改。

19(15)

/             \

11            19(15)

/   \           /   \

6    11      15    19(3)

/  \    /  \    /   \       /   \

6   2  7 11 8 15 19(3)  0

有关于数据结构的第一部分结束

-----------------------------

下面的就是数学方面的了

因为虽然这像一棵树,但是我们是不会选择用结构体建树的,而是选用数组。如果说选用数组的话,我们就要碰到一个问题了:

下标

我们所简历的是一个满“二叉树”,所以每行的都是2的几次方。我们是把数据存储在最后,所以说要算出到底是要存在哪里。当你算出2的n次方时,前面的就是2的n次方减1,所以在读数据的时候就从2的n次方开始读就可以,当然在这里浪费一个int的数组中的下标[0]没有关系,我们在这道题中会从[1]开始用。(其实也没有什么关于数学的)

而这么做的好处就是只需要log(n)

如果有1024个数
只需要10次就可以修改完

如果1000000(1024取1000为近似值)个数
也只需要20次

等等 就非常非常高效率了

-----------------------------

//以此奉上代码

#include <cstdio>

#include <cstdlib>

#include <iostream>

#define MAXN 100100

using namespace std;

int n,d[3*MAXN],q,x,y;

char c;

int main()

{

scanf("%d",&n);

int L=1;

while(L <n) L+=L; //找到合适的2的次方

for(int i=L;i<=L+n-1;i++)

scanf("%d",&d[i]);//输入

for(int i=L-1;i>=1;i--)

d[i]=max(d[2*i],d[2*i+1]);//取左右子的大数
取左子只需要2*i
右子是2*i+1 从下往上推

scanf("%d",&q);

for(int i=1;i<=q;i++)

{

getchar();//数字和字符混输别忘了getchar

scanf("%c",&c);

if(c==‘C‘)

{

scanf("%d%d",&x,&y);

d[L+x-1]=y;//替换

x=(L+x-1)/2;//上面的节点

while(x) d[x]=max(d[2*x],d[2*x+1]),x/=2;//节点不为0
就是没到头

}

else if(c==‘Q‘)

printf("%d\n",d[1]);//log(1)的取最大值,非常简洁

}

return 0;

}

//就到这里,过几天会陆续奉上正常版和加强版,see you next time!

时间: 2024-11-02 23:36:07

堆应用的相关文章

JavaScript栈和堆内存,作用域

1.栈 stack"和"堆 heap": 简单的来讲,stack上分配的内存系统自动释放,heap上分配的内存,系统不释放,哪怕程序退出,那一块内存还是在那里.stack一般是静态分配内存,heap上一般是动态分配内存. 2.基本类型和引用类型: 基本类型:存放在栈内存中的简单数据段.数据大小确定,内存空间大小可以分配. 引用类型:存放在堆内存中的对象,变量中实际保存的是一个指针,这个指针指向另一个位置.每个空间大小不一样,要根据情况开进行特定的分配. 详见<Javas

堆内存、栈内存分析图

堆内存保存的是真正的数据,简单说是对象的属性信息 栈内存保存的是对内存的地址,简单理解对象名称

JVM学习(2)——技术文章里常说的堆,栈,堆栈到底是什么,从os的角度总结--转载http://www.cnblogs.com/kubixuesheng/p/5202561.html

转载自---http://www.cnblogs.com/kubixuesheng/p/5202561.html 俗话说,自己写的代码,6个月后也是别人的代码--复习!复习!复习!涉及到的知识点总结如下: 堆栈是栈 JVM栈和本地方法栈划分 Java中的堆,栈和c/c++中的堆,栈 数据结构层面的堆,栈 os层面的堆,栈 JVM的堆,栈和os如何对应 为啥方法的调用需要栈 属于月经问题了,正好碰上有人问我这类比较基础的知识,无奈我自觉回答不是有效果,现在深入浅出的总结下: 前一篇文章总结了:JV

数据结构中的堆

一:堆排序      堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种.可以利用数组的特点快速定位指定索引的元素.堆分为大根堆和小根堆,是完全二叉树.大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i].在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶.下面附上简单C#简单实现: using System; using System.Collections.Generi

堆和栈 的区别

栈:自动回收 堆:1.内存地址  2.初始化默认值 3.垃圾回收机制 int a  = 5;  在栈中. int[] b =null;  此时null 代表 不指向任何堆. int [] c =new int[5];在堆中开辟一块空间.此时 c指一块内存地址. =======================学习黑马java视频学习的,讲的很生动,又缕了一遍.一会该练吉他了 ====以下为网上找的资料 1.在看例子之前,确保你理解以下几个术语: 栈:由JVM分配区域,用于保存线程执行的动作和数据引

桥堆的参数选择以及滤波电容的选择

1.桥堆的参数选择: 2.滤波电容选择:对于整流电压的输出电压大小,大家一定不陌生.很多人会说,输出平均值全波0.9倍,半波0.45倍的交流有效.但是在设计中,我们常常发现一个事实,例如在半波整流后,输出电压得到的不止0.45倍,9V交流整流后可能有11-12V.之前我一直很困惑,是我记错了计算倍数吗?翻了很多书籍,公式当然是没错的.那到底怎么回事? 可能之前我们在学校学这个方面知识点的时候太过注重整流电路,而忽略了脉动比的概念,所以造成我们现在很多人对这一简单的知识不是很清晰.其实这里是由于整

【堆】

看上去好像很简单的样子··然后折磨了我好久···· 主要是没仔细弄明白. 堆分为最小堆和最大堆,以二叉树的形式存在,最小堆即根节点为整个树的最小值,最大堆则是根节点为最大值. 建堆(以最大堆为例): 首先数据以数组形式存储(int a[]或vector<int> a),若二叉树的根节点从0开始计数,则节点 i 的左右子节点的下标分别为2 * i + 1和 2 * i + 2(忘了怎么算可以画一棵树,就知道了). void heap_down(int a[], int id, int numsS

《ACM/ICPC 算法训练教程》读书笔记一之数据结构(堆)

书籍简评:<ACM/ICPC 算法训练教程>这本书是余立功主编的,代码来自南京理工大学ACM集训队代码库,所以小编看过之后发现确实很实用,适合集训的时候刷题啊~~,当时是听了集训队final的意见买的,感觉还是不错滴. 相对于其他ACM书籍来说,当然如书名所言,这是一本算法训练书,有着大量的算法实战题目和代码,尽管小编还是发现了些许错误= =,有部分注释的语序习惯也有点不太合我的胃口.实战题目较多是比较水的题,但也正因此才能帮助不少新手入门,个人认为还是一本不错的算法书,当然自学还是需要下不少

POJ 3784 Running Median (最大最小堆)

最大最小堆动态求中位数 题意:输入M个数,当已输入的个数为奇数个时输出此时的中位数. 一共有M/2+1个中位数要输出,每一行10个. 分析: 用两个优先队列来模拟最大最小堆.中位数是x,就是有一半数比x小,一半数比x大. 刚好符合堆的特点. 用一个从大到小排序的优先队列q1来模拟小于x的数. 从小到大排序的优先队列q2来模拟大于x的数. 动态维护两个优先队列的元素个数.q1.size()=q2.size() 输入的数为偶数个时, q1.size()=q2.size()+1 输入的数为奇数个时.

堆VS栈

c#堆VS栈(Part One) 前言 本文主要是讲解C#语言在内存中堆.栈的使用情况,使读者能更好的理解值类型.引用类型以及线程栈.托管堆. 首先感谢原文作者:Matthew Cochran 为我们带来了一篇非常好的文章,并配以大量图示,帮助我们更好的理解堆栈之间的调用,本文是在作者原文的基础上进行内容上的精简以及加入我个人在这方面的理解和注释. 最后要感谢博客园的田志良,当我搜索堆栈内部使用时,搜索到了作者的文章,吸取了大量有用的知识,而且翻译的也非常好.唯一美中不足的可能是仅仅翻译了Mat