算法&数据结构系列 -- 堆(优先队列)
前言
话说新开的博客十分好用...
所以,我打算开一个坑,名曰【算法系列】。
什么意思——从名字泥应该就猜得出来。。。
废话不多说,进入正文~~
正文
原理
首先,堆是一颗棵二叉树。。
其次,堆是一棵完全二叉树。。
然后,设有一关系 P(Type X, Type Y)
则,堆的每个元素 Element
满足:
foreach Child ∈ Element.Childs do
ASSERT( P(Element.value, Child.value) );
说的明白点,就是每个元素和它的儿子有特定得关系。。。(忽略错别字)
所以,利用堆の性质,我们可以在O(lg n)
的时间复杂度内做一些好的事情。。。
解释(?)& 代码
1. 关于堆的存储
设v是堆里一点,则:
v*2 是 v的左儿子
v*2+1 是 v的右儿子
在实际操作中,我们常用位运算加速操作。
即:
inline int LEFT(int x) {return (x<<1);}
inline int RIGHT(int x) {return (x<<1|1);}
inline int FATHER(int x) {return (x>>1);}
2. 初始化堆
heapnum = 0;
memset(heap, 0, sizeof(heap));
3. 维护堆的性质
这是堆比较重要的一个函数。
Heapify(x) 维护以为根的字树保持堆的性质。
代码:
void Heapify(int x){
int largest;
if(LEFT(x) <= heapnum && P(heap[x],heap[LEFT(x)]))
largest = LEFT(x);
else largest = x;
if(RIGHT(x) <= heapnum && P(heap[largest], heap[RIGHT(x)]))
largest = RIGHT(x);
if(largest != x){
Exchange(heap[x], heap[largest]);
Heapify(largest);
}
}
4. UPDATE元素
该函数的作用是把x元素改为y,且必须满足P(heap[x],y)
void HeapInc(int x,int y){
heap[x] = y;
while (x > 1 && P(heap[FATHER(i)], heap[x])) {
Exchange(heap[x], heap[FATHER(x)]);
x = FATHER(x);
}
}
5. 添加元素
不说了。。。上代码:
附注:这里假设P(x,y)表示x<y, 如果P(x,y)表示x>y那么请用INF代替-INF
void HeapAdd(int x){
heap[++heapnum] = -INF;
HeapInc(heapnum, x);
}
6. 关于堆首的操作
首先 --- 返回堆首元素(哈哈,这个不会写的话···)
int Top(){
assert(heapnum >= 1); //assert(x)表示断言,如果x为false就停止程
return heap[1];
}
其次 --- 删除堆首元素
void Pop(){
assert(heapnum >= 1);
Exchange(heap[1], heap[heapnum--]);
if(heapnum) Heapify(1);
}
最后 --- 结合上面两个
int Extract(){
int val = Top();
Pop();
return val;
}
7. 其他一些东西
非空:
bool Empty(){
return heapnum == 0;
}
8. 写成一个类
神马是类?你猜····
const int N = 30000;
const int HEAPSIZE = N * 4;
template <class TElement = int, class Operator = less<int> >
class BasicHeap{
private:
TElement Plc;
TElement heap[HEAPSIZE + 5];
int heapnum;
Operator P;
inline int LEFT(int x){return x<<1;}
inline int RIGHT(int x){return x<<1|1;}
inline int FATHER(int x){return x>>1;}
inline void Exchange(TElement & x, TElement & y){TElement t = x; x = y; y = t;}
void Heapify(int x){
int largest;
if(LEFT(x) <= heapnum && P(heap[x],heap[LEFT(x)]))
largest = LEFT(x);
else largest = x;
if(RIGHT(x) <= heapnum && P(heap[largest], heap[RIGHT(x)]))
largest = RIGHT(x);
if(largest != x){
Exchange(heap[x], heap[largest]);
Heapify(largest);
}
}
inline void Assert(bool flg){
if(!flg){
abort();
}
}
public:
BasicHeap(){
heapnum = 0;
P = Operator();
}
void Inc(int x,int y){
heap[x] = y;
while (x > 1 && P(heap[FATHER(x)], heap[x])) {
Exchange(heap[x], heap[FATHER(x)]);
x = FATHER(x);
}
}
void Add(int y){
heap[++heapnum] = y;
int x = heapnum;
while (x > 1 && P(heap[FATHER(x)], heap[x])) {
Exchange(heap[x], heap[FATHER(x)]);
x = FATHER(x);
}
}
int Top(){
Assert(heapnum >= 1);
return heap[1];
}
void Pop(){
Assert(heapnum >= 1);
Exchange(heap[1], heap[heapnum--]);
if(heapnum) Heapify(1);
}
int Extract(){
int val = Top();
Pop();
return val;
}
void Clear(){
heapnum = 0;
}
bool Empty(){
return heapnum == 0;
}
};
typedef BasicHeap<> MaxHeap;
typedef BasicHeap<int, greater<int> > MinHeap;
算法&数据结构系列 -- 堆(优先队列)的更多相关文章
- 图论——Dijkstra+prim算法涉及到的优先队列(二叉堆)
[0]README 0.1)为什么有这篇文章?因为 Dijkstra算法的优先队列实现 涉及到了一种新的数据结构,即优先队列(二叉堆)的操作需要更改以适应这种新的数据结构,我们暂且吧它定义为Dista ...
- 《Algorithms算法》笔记:优先队列(2)——二叉堆
二叉堆 1 二叉堆的定义 堆是一个完全二叉树结构(除了最底下一层,其他层全是完全平衡的),如果每个结点都大于它的两个孩子,那么这个堆是有序的. 二叉堆是一组能够用堆有序的完全二叉树排序的元素,并在数组 ...
- 纯数据结构Java实现(6/11)(二叉堆&优先队列)
堆其实也是树结构(或者说基于树结构),一般可以用堆实现优先队列. 二叉堆 堆可以用于实现其他高层数据结构,比如优先队列 而要实现一个堆,可以借助二叉树,其实现称为: 二叉堆 (使用二叉树表示的堆). ...
- 数据结构与算法入门系列教程-C#
数据结构与算法入门系列教程 (一)为啥要学习数据结构与算法 曾经我也以为自己很牛逼,工作中同事也觉得我还可以,领导也看得起我,啥啥啥都好,就这样过了几年,忽然发现自己学新东西没劲.时代都变了,而我还只 ...
- 经典算法研究系列:二、Dijkstra 算法初探
July 二零一一年一月 本文主要参考:算法导论 第二版.维基百科. 一.Dijkstra 算法的介绍 Dijkstra 算法,又叫迪科斯彻算法(Dijkstra),算法解决的是有向图中单个源点到 ...
- 【JavaScript数据结构系列】00-开篇
[JavaScript数据结构系列]00-开篇 码路工人 CoderMonkey 转载请注明作者与出处 ## 0. 开篇[JavaScript数据结构与算法] 大的计划,写以下两部分: 1[JavaS ...
- 经典面试题(二)附答案 算法+数据结构+代码 微软Microsoft、谷歌Google、百度、腾讯
1.正整数序列Q中的每个元素都至少能被正整数a和b中的一个整除,现给定a和b,需要计算出Q中的前几项, 例如,当a=3,b=5,N=6时,序列为3,5,6,9,10,12 (1).设计一个函数void ...
- 【C#数据结构系列】查找
一:查找 1.1 基本概念和术语 查找(Search)是在数据结构中确定是否存在关键码等于给定关键码的记录的过程.关键码有主关键码和次关键码.主关键码能够唯一区分各个不同的记录,次关键码通常不能唯一区 ...
- 【JavaScript数据结构系列】03-队列Queue
[JavaScript数据结构系列]03-队列Queue 码路工人 CoderMonkey 转载请注明作者与出处 1. 认识队列Queue结构 队列,跟我们的日常生活非常贴近,我们前面举例了食堂排队打 ...
随机推荐
- 解决JSONObject.fromObject数字为null时被转换为0
在使用JSONObject.fromObject的时候会遇到一种情况就是当对象的某一个Double型或Integer型的属性为空的时候,转JSON的时候会变成0.当一个布尔型的属性为空的时候,转JSO ...
- Windows7下设置定时启动(关闭)虚拟机
曾记否,忆当年,开启或者关闭虚拟机,度秒如年~ ⒈石头,剪刀,布,C.D.E盘随便找一个,然后在里面找个静谧的墙角, 新建一个文件:vmstart.bat 添加:"C:\Program Fi ...
- windows server 2008使用nginx转发API异常解决办法
公司比较传统,一直使用的JSP做项目,没有遇到过跨域问题. 最近因为公司接到一个微信spa项目,因为考虑到项目需要调用老接口,斗胆选择nginx(1.12.1)做接口转发服务, 开发环境使用的win1 ...
- phpstudy php5.4以上版本伪静态设置 thinkphp
http://www.thinkphp.cn/topic/35958.html <IfModule mod_rewrite.c> Options +FollowSymlinks -Mult ...
- element-ui中upload组件如何传递文件及其他参数
最近项目用到了vuethink,里面集成了element-ui,之前一直用的是bootstrap框架,对js也是一知半解,然后也用过vue.js,但也是学的不通透的,然后就各种入坑. 下面就分析一下我 ...
- dede的pagelist标签的listsize数字属性详解
转载▼http://blog.sina.com.cn/s/blog_a4f3bd4e01012c8n.html dede的pagelist标签的listsize数字属性详解.见远seo经常用织梦搭建各 ...
- 微信小程序版2048
最近流行微信"跳一跳"小游戏,我也心血来潮写了一个微信小程序版2048,本篇文章主要分享实现2048的算法以及注意的点,一起来学习吧!(源码地址见文章末尾) 算法 1.生成4* ...
- QT5 Thread线程
QT5 Thread线程继承QThread方式 一.首先分析一下 QTimer Class与 Sleep()函数之间的秘密 QTimer *t = new QTimer(*parent); //创建Q ...
- [知了堂学习笔记]_Java代码实现MySQL数据库的备份与还原
通常在MySQL数据库的备份和恢复的时候,多是采用在cmd中执行mysql命令来实现. 例如: mysqldump -h127.0.0.1 -uroot -ppass test > d:/tes ...
- IOS 使用 ZbarSDK 二维码扫描
1. 下载SDK https://github.com/bmorton/ZBarSDK 2. 引用到项目中 3. 添加引用 4. AppDelegate中添加下面代码 5. 在需要使用扫描的con ...