• 定义

1  (二叉) 堆是一颗完全二叉树。

2   任何一个节点都小于它的后裔节点。(最小堆),相应的,最大堆中的任何一个节点大于它的后裔节点。

由于二叉堆是一个完全二叉树,因此对于二叉堆中的任何一个节点i,它的子节点的编号为:

A[ left ]  =  A[ 2*i + 1 ]     ;      A[ right ] = A [ 2*i + 2 ]   (注:这是与实际实现时相对应的,比如如下的堆:)

由于堆的完全二叉树的性质,我们使用数组来表示堆即可。如下图所示:

左图是一个大顶堆,堆顶的元素是最大的。下方的数组是与该堆对应的。(注:上述的数组的有序是纯属偶然的。)

首要的,堆的操作最重要的性质便是保持堆序性。也就是说我们在加入元素以及删除元素(一般是删除堆顶)之后,需要对堆作出调整,使得堆依旧满足堆序性。

  • 插入元素

向堆中加入新的元素i,输入:要添加的元素elem。使得加入后依然是堆。简单的示意图如下:

                 插入元素15,那么需要判断15是否破坏了堆序性,即是否该元素放在了正确的位置,显然 15 > 10,不满足堆序性,因此15上滤,得到右图,由于 15 < 18,说明15到达了正确的位置,因此成功插入了元素15.

  • 保持堆序性:

这是堆的所有操作的最重要的一个函数:通过递归的比较当前元素与它的左右子节点,决定是否将该元素下滤,直到到达正确的位置。

C++代码如下:

//max heapify for the i-th elem in A
void max_heapify(int A[], int  i, int heap_size)
{int largest = i;int left = 2*i+1;int right = 2*i+2;if(left < heap_size && A[left] > A[largest]){largest = left;}if(right < heap_size && A[right] > A[largest]){largest = right;}if(largest != i){swap(A[i],A[largest]);max_heapify(A,largest,heap_size);}
}
  • 建堆

给定数组A,要求将A变成一个堆,也就是说逐渐改变数组A中的元素位置,使得数组保持堆序性。

假设给定数组A   =  {  3   13    2    8   18   10 },要将该数组构建成一个最大堆。

首先,在构建最大堆之前,必须明确:

1    由完全二叉树的性质,数组的至少一半的元素为叶子节点:

一个简单的例子:对于一颗整的完全二叉树而言,第 i  层的元素个数为 2^(i-1),(根节点为第0层!!注意与平时树的高度的区别)。那么有如下示意图:


因此,前i层的节点总数为:

1 + 2 + 2^2 + ... + 2^(i-1) = 2^i - 1

第i+1层(即叶子节点层)的节点个数为2^i ,因此叶子节点的个数大约为总节点个数的一半。

另一方面想,由于完全二叉树中父节点与子节点之间的位置关系,也可以知道对于某个节点i而言,如果它的右孩子编号大于整个数组的大小,那么显然节点i是最后一个中间节点,它后面的节点应该全部为叶子节点。即

2*i+2 =  len, 那么 i = ( len - 2 ) / 2。因此基于此我们建堆的过程只需要考虑数组中的前一半的元素,代码如下:

void build_max_heap(int A[], int len)
{for(int i = len/2 ; i >= 0 ; i--){max_heapify(A,i,len);}
}
  • 堆排序:

由于每一次从堆中找出最大的元素(大顶堆)是很直接的,直接取出对顶元素即可,那么在删除堆顶的元素之后:

1    堆中的元素个数会减一

2    堆顶空缺,需要将剩下的最大的元素放置在堆顶

如下的简单示意图:

按照上述一直到堆中的元素为0,那么数组中的元素也就有序了(从小到大有序)。

代码如下:

void heapSort(int A[], int len)
{build_max_heap(A,len);//printHeap(A,len);for(int i = len-1; i >= 0 ; --i){swap(A[i],A[0]);max_heapify(A,0,i);}
}

因此,堆排序实现完毕。

注:如果你是要将数组从大到小的排序,那么你应该建立的是小顶堆,否则为大顶堆。

堆的各种操作大致都是堆的高度O(logn)量级的。

总结:堆是很重要的数据结构,在任务优先级调度方面可作为优先级队列来使用,每次选择优先级最高的任务。

堆的操作还有很多,比如改变某个关键字的值,或者是删除中间的某个关键字。值得一提的是,堆排序是一种in-place排序,复杂度为O(nlogn)。

补充:由于在实现堆的时候,老是要去画二叉树,于是自己实现了一个简陋的只针对于完全二叉树的程序:

static void printSpace(int number)
{while(number--)cout << " ";
}
void printHeap(int A[], int len)
{if(len == 0 ){cout << "len == 0 !!!" << endl;return;}int level = log10(len)/log10(2)+1;//得到树的高度cout << "level = " << level << endl;printSpace(level*2);cout << A[0];printSpace(level*2);level--;cout << endl;int index = 1;for(int i = 0;i < level; ++i ){int count = pow(2,i);while(count--){printSpace((level-i)*2);if(index < len) cout << A[index++];printSpace((level-i)*2);if(index < len)cout << A[index++];printSpace(count);}cout << endl;}
}

PS:简陋的程序,只能用于画完全二叉树。

[data structure] heap 堆相关推荐

  1. bss,data,text,rodata,堆,栈,常量段

    //红色部分为问题部分 section 结构 SECTIONS { ... secname start BLOCK(align) (NOLOAD) : AT ( ldadr )   { content ...

  2. linux代码段映射,bss,data,text,rodata,堆,栈,常量段与其各段在物理存储中关系

    本文想从linux出发[目前还想可不可以从51单片机出发],解答程序代码和各种数据结构是如何存储(映射)到存储区的. 目前未完成整理,还是初稿的想法.bss段: BSS段(bsssegment)通常是 ...

  3. Data Structure

    Data Structure 1. Abstract Data Type (ADT) 1.1. Data type A set of objects + a set of operations Exa ...

  4. linux 目标文件(*.o) bss,data,text,rodata,堆,栈

    学习于:http://blog.csdn.net/sunny04/article/details/40627311 linux目标文件 一个简单的程序被编译成目标文件后的结构如下: 注:初始化为0在此 ...

  5. CF data structure 自制题单(一)

    CF data structure 2000~2100 为你的战斗,献上雷鸣般的喝彩!--唔姆 目标 30 道题 1. Problem - 1555E - Codeforces 看了提示 给一些线段, ...

  6. [Java]Stack栈和Heap堆的区别(终结篇)[转]

    首先分清楚Stack,Heap的中文翻译:Stack-栈,Heap-堆. 在中文里,Stack可以翻译为"堆栈",所以我直接查找了计算机术语里面堆和栈开头的词语: 堆存储: hea ...

  7. LeetCode Two Sum III - Data structure design

    原题链接在这里:https://leetcode.com/problems/two-sum-iii-data-structure-design/ 题目: Design and implement a ...

  8. leetcode 211. Add and Search Word - Data structure design Trie树

    题目链接 写一个数据结构, 支持两种操作. 加入一个字符串, 查找一个字符串是否存在.查找的时候, '.'可以代表任意一个字符. 显然是Trie树, 添加就是正常的添加, 查找的时候只要dfs查找就可 ...

  9. leetcode Add and Search Word - Data structure design

    我要在这里装个逼啦 class WordDictionary(object):def __init__(self):"""initialize your data str ...

最新文章

  1. Linux文件夹分析
  2. 19课 Vue第二节
  3. 集群节点间的延迟问题
  4. Michael Nygard on Building Resilient Systems
  5. 封装EF code first用存储过程的分页方法
  6. Go Web编程--应用ORM
  7. php 生成饼状图,折线图,条形图 通用类
  8. OpenCV_cv::Mat的深拷贝 浅拷贝问题
  9. 你的核心竞争力真的是技术么?
  10. linux qq 提示错误,deepin-wine QQ崩溃,QQ遇到错误的暂时解决方法
  11. 中国将在未来几十年主导电动汽车市场
  12. 数字图像处理 总复习(第七章)*秋昊
  13. 疫情已经2年半,中国IT厂商该有一些经验教训和改变了
  14. 如何debug preloader bootup time 问题以及开机过程中preloader慢抓取 preload模块开机log
  15. nodejs:underscore模块介绍
  16. win7系统备份还原软件_非常好用的系统备份和还原的软件,OneKey一键还原工具
  17. 阿里最受追捧的「中高级技术核心」,助我拿下裹裹offer,附面经
  18. typescript Type 'NodeListOfany' must have a '[Symbol.iterator]()' method that returns an iterato
  19. java结账_java 基础程序之商场结账管理
  20. 云管平台如何纳管多云资源?

热门文章

  1. Everything Is Generated In Equal Probability(HDU - 6595,概率期望)
  2. python的iloc与loc函数
  3. 生信学习笔记:fastp质控处理生成的report结果解读
  4. 优思学院|质量大师的那些名言(一)【质量是免费的】
  5. AD20——批量快速放置元件管脚
  6. 什么是MIL、SIL、PIL和HIL?
  7. java实现第二届蓝桥杯地铁换乘(C++)
  8. 【行为分析】(一)宏观简介
  9. 内测“今视频”APP入局长视频,快手有钱之后“飘了”?
  10. R语言用GAM广义相加模型研究公交专用道对行程时间变异度数据的影响