堆,是优先队列最常用的一种实现方式。在优先队列中,每个元素都被赋予了一个优先级,而每次出队时都让优先级最高的元素出队。堆,则是一种存储优先队列的方法,特指以一棵树形式存储的优先队列。最常用的是二叉堆,但既然是专门介绍数据结构,就不妨说全一些,我们取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++代码 堆(优先队列)的更多相关文章

  1. 纯数据结构Java实现(6/11)(二叉堆&优先队列)

    堆其实也是树结构(或者说基于树结构),一般可以用堆实现优先队列. 二叉堆 堆可以用于实现其他高层数据结构,比如优先队列 而要实现一个堆,可以借助二叉树,其实现称为: 二叉堆 (使用二叉树表示的堆). ...

  2. 算法&数据结构系列 -- 堆(优先队列)

    前言 话说新开的博客十分好用... 所以,我打算开一个坑,名曰[算法系列]. 什么意思--从名字泥应该就猜得出来... 废话不多说,进入正文~~ 正文 原理 首先,堆是一颗棵二叉树.. 其次,堆是一棵 ...

  3. 数据结构(栈&堆 )

    在计算机领域,堆栈是一个不容忽视的概念,堆栈是两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除.在单片机应用中,堆栈是个特殊的存储区,主要功能 ...

  4. POJ 2010 - Moo University - Financial Aid 初探数据结构 二叉堆

    考虑到数据结构短板严重,从计算几何换换口味= = 二叉堆 简介 堆总保持每个节点小于(大于)父亲节点.这样的堆被称作大根堆(小根堆). 顾名思义,大根堆的数根是堆内的最大元素. 堆的意义在于能快速O( ...

  5. Java数据结构和算法 - 堆

    堆的介绍 Q: 什么是堆? A: 这里的“堆”是指一种特殊的二叉树,不要和Java.C/C++等编程语言里的“堆”混淆,后者指的是程序员用new能得到的计算机内存的可用部分 A: 堆是有如下特点的二叉 ...

  6. POJ 2442 - Sequence - [小顶堆][优先队列]

    题目链接:http://poj.org/problem?id=2442 Time Limit: 6000MS Memory Limit: 65536K Description Given m sequ ...

  7. 【bzoj2151】种树(堆/优先队列+双向链表)

    题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2151 这道题因为优先队列不怎么会用,而且手写堆的代码也不长,也想复习一下手写堆的写法…… ...

  8. 堆&&优先队列&&TreeMap

    题目描述 5710. 积压订单中的订单总数 题解 题目不难,主要是要读懂题意,一步步模拟,代码较长,需要细心检查. 坑较多,比如我犯了很多傻逼问题:想都不想就拿1<<9+7当作100000 ...

  9. 数据结构作业——Sanji(优先队列)

    山治的婚约 Description 我们知道,山治原来是地下有名的杀人家族文斯莫克家族的三子,目前山治的弟弟已经出现,叫做四治,大哥二哥就叫汪(One)治跟突(Two)治好了(跟本剧情无关) .山治知 ...

随机推荐

  1. 官方发布PHP语法规范

    PHP语言已经存在了超过20年,显然是世界上最流行的编程语言之一.PHP绝对是互联网服务器端web编程的通用语. 虽然有广泛的user-documentation,PHP语言总是错过语言规范.这并不是 ...

  2. 起一个node服务

    使用node开发一个应用,非常简单,甚至都不用去配置一堆文件来启动一个webu服务器,直接去官网把这一段示例代码拷过来 https://nodejs.org/en/about/ 中文网没有这个abou ...

  3. react里面引入图片

    引入图片确实走了很多的坑,开始的认知里,所有静态页面都需要放在public里面能执行,代码是这样的 css .back{ background-image: url('/images/homeBack ...

  4. [Python]面向对象近期笔记-super

    Python面向对象高级 直接调用父类方法 class A: def __init__(self): print("hello") class B(A): def __init__ ...

  5. 整个trick

    数据输入方面:1.image pyramid 图像金字塔.目前代码里是先选取一个scale,然后在每个GPU上按照scale读图片,相应的gt也更改."scales":[440, ...

  6. wcf 的小介绍

    http://www.cnblogs.com/scottckt/archive/2010/10/15/1852136.html

  7. centos7 kvm安装使用

    kvm简介 KVM 全称是 Kernel-Based Virtual Machine.也就是说 KVM 是基于 Linux 内核实现的. KVM有一个内核模块叫 kvm.ko,只用于管理虚拟 CPU ...

  8. Notepad++配色方案

    1.下载notepad++样式文件 styles.xml 2.将该文件拷贝到 C:\Users\Administrator\AppData\Roaming\Notepad++ 目录(将Administ ...

  9. chrome 浏览器插件开发(二)—— 通信 获取页面变量 编写chrome插件专用的库

    在chrome插件的开发过程中,我遇到了一些问题,在网上找了不少文章,可能是浏览器升级的原因,有一些是有效的也有无效的.下面我简单的分享一下我遇到的坑,以及我把这些坑的解决方案整理而成的js库 —— ...

  10. iOS第三方支付(支付宝)

    使用支付宝进行一个完整的支付功能,大致有以下步骤: 与支付宝签约,获得商户ID(partner)和账号ID(seller) 下载相应的公钥私钥文件(加密签名用) 下载支付宝SDK 生成订单信息 调用支 ...