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. 在oracle中操作表及字段注释,查询一个表的所有字段名以及属性和约束

    1.查询表注释 SELECT * FROM USER_TAB_COMMENTS; 三列:TABLE_NAME,TABLE_TYPE,COMMENTS 2.查询字段注释 SELECT * FROM US ...

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

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

  3. ios-UI1

    // AppDelegate.h // 01-HelloWorld的实现 // /* 新建工程的时候,Use Core Data:比如本地缓存, Include Unit test:增加单元测试 In ...

  4. jQuery Validate插件实现表单强大的验证功能

    转自:http://www.jb51.net/article/76595.htm jQuery Validate插件捆绑了一套有用的验证方法,包括 URL 和电子邮件验证,同时提供了一个用来编写用户自 ...

  5. [Swift通天遁地]二、表格表单-(5)实现表格下拉和上拉刷新效果

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  6. asp.net core 2.0 Json结果的格式

    asp.net core 2.0 默认返回的结果格式是Json, 并使用json.net对结果默认做了camel case的转化(大概可理解为首字母小写). 这一点与老.net web api 不一样 ...

  7. BZOJ 3473

    思路: CF原题 ZYF有题解 O(nlog^2n) //By SiriusRen #include <bits/stdc++.h> using namespace std; ; ]; i ...

  8. IMP-00058 ORA-12638:身份证明检索失败

    需要将oracle的tns关掉 1.打开 oracle 的Net Manage 地址:开始 -> 程序 -> Oracle -> Configuration and Migratio ...

  9. Python安装distribute包

    从官网https://pypi.python.org/pypi/distribute/0.6.49#downloads上下载distribute包,解压后进入解压文件的目录下,使用 python se ...

  10. 胖ap和瘦ap的区别

    一,什么是AP,胖瘦AP如何区分?       先说说AP的概念.AP是Access Point的简称,即无线接入点,其作用是把局域网里通过双绞线传输的有线信号(即电信号)经过编译,转换成无线电信号传 ...