《数据结构》C++代码 堆(优先队列)
堆,是优先队列最常用的一种实现方式。在优先队列中,每个元素都被赋予了一个优先级,而每次出队时都让优先级最高的元素出队。堆,则是一种存储优先队列的方法,特指以一棵树形式存储的优先队列。最常用的是二叉堆,但既然是专门介绍数据结构,就不妨说全一些,我们取4个典型的堆进行比较,见下表(此表及表下备注,来自于广东省中山市第一中学黄源河前辈的《左偏树的特点及其应用》,并做过言辞修改及内容补充):
|
项目 |
二叉堆 |
左偏树 |
二项堆 |
Fibonacci堆 |
|
构建 |
O(n) |
O(n) |
O(n) |
O(n) |
|
插入 |
O(logn) |
O(logn) |
O(logn) |
O(1) |
|
取最小点 |
O(1) |
O(1) |
O(logn) |
O(1) |
|
删除最小点 |
O(logn) |
O(logn) |
O(logn) |
O(logn) |
|
删除任意点 |
O(logn) |
O(logn) |
O(logn) |
O(logn) |
|
合并 |
O(n) |
O(logn) |
O(logn) |
O(1) |
|
空间需求 |
最小 |
较小 |
一般 |
较大 |
|
编程复杂度 |
最低 |
较低 |
较高 |
很高 |
在此说明几点:
0、二项堆又称Bernoulli堆,左偏树又称左堆;斜堆并未在表中列出,是由于其复杂度与左偏树相同,没必要单独列出。其代码更简单,但常数较大,且在特殊数据下可能退化成O(n)。它与左偏树的关系,就像Splay与AVL的关系,并无优劣之分,前者更简洁灵活而后者更快。另外,我并未谈及D堆,那是因为这类仅在接触外存才值得应用的堆,我并不想提及。大家在考试用不上,平时也用不上,故而在我看来暂时了解、理解就好,之后真正用到了再去深究不迟。
1、二项堆,其“取最小点”的复杂度是O(log n),可以改进为O(1)。方法是,随时记录最小节点,并只在插入、删除以及合并等操作进行的时候更新该记录。
2、二项堆,其“插入”操作的平均时间复杂度为O(1),表中给出的是最坏时间复杂度。
3、Fibonacci堆,其“删除最小点”和“删除任意点”两个操作的时间复杂度均为平摊时间复杂度。
可能大家并未了解全,那就请自行搜索吧,我在此仅仅给出实现代码。由于种类过多,我仅仅对每种堆给出一种最常见的实现方式(例如二叉堆仅仅给出数组实现法),大家视题目需要而融会贯通即可。另外,由于代码较长,为了方便大家比较,我仅仅给出类版,实际实现时,不写成类有时反而方便许多。
还有,我依旧假设每个元素的信息仅有一个int权值,这样可以让大家更关注代码的框架结构,而不至于在繁琐的代码中看得迷迷糊糊。真正使用时,如果元素信息增多,视情况修改即可。
代码:
// 本代码所实现的是最小堆
const int maxk = ;
const int maxn = ;
inline swap(int &x,int &y) { int t=x; x=y; y=t; } // 二叉堆
// 实现了init、in、out操作
class Two_Heap
{
int H[maxn+],L; // H[1~L]是堆中元素
void up(int j)
{
int i=j>>;
if(i== || H[i]<H[j]) return;
swap(H[i],H[j]); up(i);
}
void down(int i)
{
int j=i<<;
if(j<L && H[j+]<H[j]) ++j;
if(j>L || H[i]<H[j]) return;
swap(H[i],H[j]); down(j);
}
public:
Two_Heap():L() {}
void init(int A[],int N)
{
// 以一个数组A[1~N]去初始化堆,这是堆排中建堆的过程,复杂度O(N)
L=N;
for(int i=;i<=N;++i) H[i]=A[i];
for(int i=N>>;i>=;--i) down(i); // 可以证明,从N/2开始调整即可,后N/2个点必然是叶子结点
}
void in(int x) { A[++L]=x; up(L); }
int out() { swap(A[],A[L--]); down(); return A[L+]; }
int min() { return A[]; }
}; // 未完待续
《数据结构》C++代码 堆(优先队列)的更多相关文章
- 纯数据结构Java实现(6/11)(二叉堆&优先队列)
堆其实也是树结构(或者说基于树结构),一般可以用堆实现优先队列. 二叉堆 堆可以用于实现其他高层数据结构,比如优先队列 而要实现一个堆,可以借助二叉树,其实现称为: 二叉堆 (使用二叉树表示的堆). ...
- 算法&数据结构系列 -- 堆(优先队列)
前言 话说新开的博客十分好用... 所以,我打算开一个坑,名曰[算法系列]. 什么意思--从名字泥应该就猜得出来... 废话不多说,进入正文~~ 正文 原理 首先,堆是一颗棵二叉树.. 其次,堆是一棵 ...
- 数据结构(栈&堆 )
在计算机领域,堆栈是一个不容忽视的概念,堆栈是两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除.在单片机应用中,堆栈是个特殊的存储区,主要功能 ...
- POJ 2010 - Moo University - Financial Aid 初探数据结构 二叉堆
考虑到数据结构短板严重,从计算几何换换口味= = 二叉堆 简介 堆总保持每个节点小于(大于)父亲节点.这样的堆被称作大根堆(小根堆). 顾名思义,大根堆的数根是堆内的最大元素. 堆的意义在于能快速O( ...
- Java数据结构和算法 - 堆
堆的介绍 Q: 什么是堆? A: 这里的“堆”是指一种特殊的二叉树,不要和Java.C/C++等编程语言里的“堆”混淆,后者指的是程序员用new能得到的计算机内存的可用部分 A: 堆是有如下特点的二叉 ...
- POJ 2442 - Sequence - [小顶堆][优先队列]
题目链接:http://poj.org/problem?id=2442 Time Limit: 6000MS Memory Limit: 65536K Description Given m sequ ...
- 【bzoj2151】种树(堆/优先队列+双向链表)
题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2151 这道题因为优先队列不怎么会用,而且手写堆的代码也不长,也想复习一下手写堆的写法…… ...
- 堆&&优先队列&&TreeMap
题目描述 5710. 积压订单中的订单总数 题解 题目不难,主要是要读懂题意,一步步模拟,代码较长,需要细心检查. 坑较多,比如我犯了很多傻逼问题:想都不想就拿1<<9+7当作100000 ...
- 数据结构作业——Sanji(优先队列)
山治的婚约 Description 我们知道,山治原来是地下有名的杀人家族文斯莫克家族的三子,目前山治的弟弟已经出现,叫做四治,大哥二哥就叫汪(One)治跟突(Two)治好了(跟本剧情无关) .山治知 ...
随机推荐
- 官方发布PHP语法规范
PHP语言已经存在了超过20年,显然是世界上最流行的编程语言之一.PHP绝对是互联网服务器端web编程的通用语. 虽然有广泛的user-documentation,PHP语言总是错过语言规范.这并不是 ...
- 起一个node服务
使用node开发一个应用,非常简单,甚至都不用去配置一堆文件来启动一个webu服务器,直接去官网把这一段示例代码拷过来 https://nodejs.org/en/about/ 中文网没有这个abou ...
- react里面引入图片
引入图片确实走了很多的坑,开始的认知里,所有静态页面都需要放在public里面能执行,代码是这样的 css .back{ background-image: url('/images/homeBack ...
- [Python]面向对象近期笔记-super
Python面向对象高级 直接调用父类方法 class A: def __init__(self): print("hello") class B(A): def __init__ ...
- 整个trick
数据输入方面:1.image pyramid 图像金字塔.目前代码里是先选取一个scale,然后在每个GPU上按照scale读图片,相应的gt也更改."scales":[440, ...
- wcf 的小介绍
http://www.cnblogs.com/scottckt/archive/2010/10/15/1852136.html
- centos7 kvm安装使用
kvm简介 KVM 全称是 Kernel-Based Virtual Machine.也就是说 KVM 是基于 Linux 内核实现的. KVM有一个内核模块叫 kvm.ko,只用于管理虚拟 CPU ...
- Notepad++配色方案
1.下载notepad++样式文件 styles.xml 2.将该文件拷贝到 C:\Users\Administrator\AppData\Roaming\Notepad++ 目录(将Administ ...
- chrome 浏览器插件开发(二)—— 通信 获取页面变量 编写chrome插件专用的库
在chrome插件的开发过程中,我遇到了一些问题,在网上找了不少文章,可能是浏览器升级的原因,有一些是有效的也有无效的.下面我简单的分享一下我遇到的坑,以及我把这些坑的解决方案整理而成的js库 —— ...
- iOS第三方支付(支付宝)
使用支付宝进行一个完整的支付功能,大致有以下步骤: 与支付宝签约,获得商户ID(partner)和账号ID(seller) 下载相应的公钥私钥文件(加密签名用) 下载支付宝SDK 生成订单信息 调用支 ...