binary heap就是一种complete binary tree(完全二叉树)。也就是说,整棵binary tree除了最底层的叶节点之外,都是满的。而最底层的叶节点由左至右又不得有空隙。

以上是一个对heap的简单介绍。本文将用heap指代此种完全二叉树。那么在实际编写代码的时候怎么组织这种数据呢,其实可以用array来存储这种结构的数据。将数组的第0个元素保留不用,从第一个元素开始存放数据。那么,对于树中的某个位于i的节点,其左子节点必然位于2i处,右子节点必然位于2i+1处,父节点必然位于“i/2”处。当然heap要能动态的改变大小,所以用vector存储数据会更好。

这里还有一个小的细节需要注意一下,heap可以分为max-heap以及min-heap,前者每个节点的键值都大于或等于其子节点键值,后者的每个节点键值都小于或等于其子节点键值。可以推出,max-heap的最大键值在根节点,min-heap的最小键值在根节点。

综上:heap就是一个包含了一组数据(通常可用array/vector来存储)以及一组管理这些数据的算法(插入元素,删除元素,取极值,将一组数据排列成一个heap)。通过这些方法可以保证heap的特性。

heap的算法

因为在c++ stl中并不直接提供heap这样一种数据结构,但它却是很多数据结构的基础:例如优先队列。所以这里我们主要关注的是heap涉及到的一些算法。

push_heap

在很多书籍当中,通常通过一个上浮的操作来完成push_heap。其基本原理可见下图(假设新加入的元素是50):

  1. 将50插入到数组的末尾。
  2. 将其于父元素相比较,发现24小于50,交换这两个元素。上浮一次
  3. 继续上述操作直到找到一个合适的位置,也即其父元素大于50的位置,则上浮结束。

一个简易的c++实现:

template<typename T>
void push_heap(std::vector<T> &vec, T value)
{
vec.push_back(value);
int i = vec.size()-1;
while (i > 1 && vec[i] > vec[i / 2]) {
std::swap(vec[i], vec[i / 2]);
i = i / 2;
}
}

pop_heap

pop操作是类似的:

  1. 将最后一个元素与第一个元素(根元素)交换。
  2. 删除最后一个元素。
  3. 将第一个元素/根元素下沉到一个合适的位置。注意下沉的时候是与子节点较大的那个元素交换。

一个简易的c++实现:

template<typename T>
T pop_heap(std::vector<T> &vec)
{
int i = 1;
//将最后元素与第一个元素(根元素)交换, 然后删除最后一个元素
std::swap(vec[1], vec[vec.size() - 1]);
T v = vec[vec.size() - 1];
vec.pop_back(); //将现在的第一个元素/根元素下沉到一个合适的位置
while (2 * i < vec.size()) {
int j = 2 * i; //左子节点
if (j < vec.size() - 1 && vec[j] < vec[j + 1]) j++;
if (vec[j] < vec[i]) break;
std::swap(vec[i], vec[j]);
i = j;
}
return v;
}

sort_heap

sort_heap是利用heap每次都取出极值(这里是max)的特性进行排序。那么只要进行n次pop_heap即可完成排序。

template<typename T>
void sort_heap(std::vector<T> &vec)
{
std::vector<T> temvec;
int size = vec.size()-1;
while (size != 0) {
temvec.push_back(pop_heap(vec));
size--;
}
for (T value : temvec) {
vec.push_back(value);
}
}

See you next time. Happy Coding!!!

我的github

数据结构与算法(6) -- heap的更多相关文章

  1. 数据结构与算法---堆排序(Heap sort)

    堆排序基本介绍 1.堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序. 2.堆是具有以下性质的完全二叉树:每个 ...

  2. 数据结构与算法--堆(heap)与栈(stack)的区别

    堆和栈的区别 在C.C++编程中,经常需要操作的内存可分为以下几个类别: 栈区(stack):由编译器自动分配和释放,存放函数的参数值,局部变量的值等,其操作方式类似于数据结构中的栈. 堆区(heap ...

  3. 数据结构与算法 Big O 备忘录与现实

    不论今天的计算机技术变化,新技术的出现,所有都是来自数据结构与算法基础.我们需要温故而知新.        算法.架构.策略.机器学习之间的关系.在过往和技术人员交流时,很多人对算法和架构之间的关系感 ...

  4. python 下的数据结构与算法---1:让一切从无关开始

    这段时间把<Data Structure and Algorithms with python>以及<Problem Solving with  Algorithms and Dat ...

  5. Java数据结构和算法(十四)——堆

    在Java数据结构和算法(五)——队列中我们介绍了优先级队列,优先级队列是一种抽象数据类型(ADT),它提供了删除最大(或最小)关键字值的数据项的方法,插入数据项的方法,优先级队列可以用有序数组来实现 ...

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

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

  7. Java数据结构和算法 - OverView

    Q: 为什么要学习数据结构与算法? A: 如果说Java语言是自动档轿车,C语言就是手动档吉普.数据结构呢?是变速箱的工作原理.你完全可以不知道变速箱怎样工作,就把自动档的车子从1档开到4档,而且未必 ...

  8. Python3-Cookbook总结 - 第一章:数据结构和算法

    第一章:数据结构和算法 Python 提供了大量的内置数据结构,包括列表,集合以及字典.大多数情况下使用这些数据结构是很简单的. 但是,我们也会经常碰到到诸如查询,排序和过滤等等这些普遍存在的问题. ...

  9. Java的数组,集合,数据结构,算法(一)

    本人的愚见,博客是自己积累对外的输出,在学习初期或自己没有多少底料的情况下,与其总结写博客不如默默去搞自己的代码,但是学到集合这一块时,数组,集合,数据结构,算法这个概念搞的我比较混淆,所以不得已写这 ...

随机推荐

  1. 改善java程序的151个建议--数组和集合

    60.性能考虑,数组是首选,在基本类型处理方面.数组还是占优势的,并且集合类的底层也都是通过数组实现.建议在性能要求较高的场景中使用数组替代集合. 61.假设有必要.使用变长数组:我们能够通过对数组扩 ...

  2. USACO zerosum DFS 1A

    USER: Kevin Samuel [kevin_s1] TASK: zerosum LANG: C++ Compiling... Compile: OK Executing... Test 1: ...

  3. 【cocos2d-x-3.1.1系列5】cocos2d-x 引用计数细节

    看了引用计数之后  那时好像懂了   今天突然想起一个问题: Scene也是继承自Ref .然后也是静态生成一个autorelease后的对象  那计数就变成1了 class CC_DLL Scene ...

  4. Data Url生成工具之HTML5 FileReader实现

    百度经验版本号:怎样用HTML5的FileReader生成Data Url 上一篇讲了:用Visual Studio 2010编写Data Url生成工具C#版 今天用HTML5 FileReader ...

  5. java.lang.NoClassDefFoundError: org/apache/commons/lang/xwork/StringUtils

    java.lang.NoClassDefFoundError: org/apache/commons/lang/xwork/StringUtils Struts2框架下使用JSON插件时.程序保存找不 ...

  6. 使用WCF进行跨平台开发之一(WCF的实现、控制台托管与.net平台的调用)

    WCF是Windows Communication Foundation的缩写,是微软发展的一组数据通信的应用程序开发接口,它是.NET框架的一部分,是WinFx的三个重要开发类库之一,其它两个是WP ...

  7. UVA 1640(DFS)

    题意:给你a,b两个数 问你a b区间中0 9出现的次数 其实就是求1-n中0-9出现的次数 ans[n]   答案就是ans[b]-ans[a-1] 怎么求的话看代码吧 #include<io ...

  8. C++11系列-什么是C++11

    什么是C++0x? C++0x是C++最新标准标准化过程中的曾用名,在这一系列文章中我们将介绍最新标准添加的一系列新的语言特性.在2011年9月份,C++0x正式由官方发布并命名C++11,现在很多编 ...

  9. bzoj1477 && exgcd学习笔记

    exgcd 由于忘记了exgcd,这道题就没做出来... exgcd的用处是求ax+by=gcd(a,b)这样方程的解 大概是这个样子的 void ext_gcd(long long a, long ...

  10. Secure CRT中解决vim高亮设置的方法

    此文主要是解决vim编程中高亮显示的.原因是: 1.默认情况下,SecureCRT是有自己的终端显示颜色.这样在我们编程中不利于阅读内容. 2.我们必须到Linux系统中进行改进才能真正解决这样的问题 ...