堆常用来实现优先队列,在这种队列中,待删除的元素为优先级最高(最低)的那个。在任何时候,任意优先元素都是可以插入到队列中去的,是计算机科学中一类特殊的数据结构的统称

一、堆的定义

最大(最小)堆是一棵每一个节点的键值都不小于(大于)其孩子(如果存在)的键值的树。大顶堆是一棵完全二叉树,同时也是一棵最大树。小顶堆是一棵完全完全二叉树,同时也是一棵最小树。

注意:

  • 堆中任一子树亦是堆。
  • 以上讨论的堆实际上是二叉堆(Binary Heap),类似地可定义k叉堆。

下图分别给出几个最大堆和最小堆的例子:

二、支持的基本操作

堆支持以下的基本操作:

  • build: 建立一个空堆;
  • insert: 向堆中插入一个新元素;
  • update:将新元素提升使其符合堆的性质;
  • get:获取当前堆顶元素的值;
  • delete:删除堆顶元素;
  • heapify:使删除堆顶元素的堆再次成为堆。

某些堆实现还支持其他的一些操作,如斐波那契堆支持检查一个堆中是否存在某个元素。

三、堆的应用

1.堆排序

堆排序(HeapSort)是一树形选择排序。
     堆排序的特点是:在排序过程中,将R[l..n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系【参见二叉树的顺序存储结构】,在当前无序区中选择关键字最大(或最小)的记录。
优点直接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录,又需要做n-2次比较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行了这些比较操作。
堆排序可通过树形结构保存部分比较结果,可减少比较次数。
堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。
(1)、用大根堆排序的基本思想

  • 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区
  • 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key
  • 由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。直到无序区只有一个元素为止。

(2)、大根堆排序算法的基本操作:

  • 初始化操作:将R[1..n]构造为初始堆;
  • 每一趟排序的基本操作:将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。

注意:

  • 只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。
  • 用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。堆排序和直接选择排序相反:在任何时刻,堆排序中无序区总是在有序区之前,且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止。

(3)、算法实现

  1. //堆排序
  2. template <class T>
  3. void Sort::HeapSort(T arr[], int len){
  4. int i;
  5. //建立子堆
  6. for(i = len / 2; i >= 1; i--){
  7. CreateHeap(arr, i, len);
  8. }
  9. for(i = len - 1; i >= 1; i--){
  10. buff = arr[1];
  11. arr[1] = arr[i + 1];
  12. arr[i + 1] = buff;
  13. CreateHeap(arr, 1, i);
  14. }
  15. }
  16. //建立堆
  17. template <class T>
  18. void Sort::CreateHeap(T arr[], int root, int len){
  19. int j = 2 * root;                   //root's left child, right (2 * root + 1)
  20. T temp = arr[root];
  21. bool flags = false;
  22. while(j <= len && !flags){
  23. if(j < len){
  24. if(arr[j] < arr[j + 1]){     // Left child is less then right child
  25. ++j;                // Move the index to the right child
  26. }
  27. }
  28. if(temp < arr[j]){
  29. arr[j / 2] = arr[j];
  30. j *= 2;
  31. }else{
  32. flags = true;
  33. }
  34. }
  35. arr[j / 2]  = temp;
  36. }

2.选择前k个最大(最小)的数

思想:在一个很大的无序数组里面选择前k个最大(最小)的数据,最直观的做法是把数组里面的数据全部排好序,然后输出前面最大(最小)的k个数据。但是,排序最好需要O(nlogn)的时间,而且我们不需要前k个最大(最小)的元素是有序的。这个时候我们可以建立k个元素的最小堆(得出前k个最大值)或者最大堆(得到前k个最小值),我们只需要遍历一遍数组,在把元素插入到堆中去只需要logk的时间,这个速度是很乐观的。利用堆得出前k个最大(最小)元素特别适合海量数据的处理。

代码:

  1. typedef multiset<int, greater<int> >            intSet;
  2. typedef multiset<int, greater<int> >::iterator  setIterator;
  3. void GetLeastNumbers(const vector<int>& data, intSet& leastNumbers, int k)
  4. {
  5. leastNumbers.clear();
  6. if(k < 1 || data.size() < k)
  7. return;
  8. vector<int>::const_iterator iter = data.begin();
  9. for(; iter != data.end(); ++ iter)
  10. {
  11. if((leastNumbers.size()) < k)
  12. leastNumbers.insert(*iter);
  13. else
  14. {
  15. setIterator iterGreatest = leastNumbers.begin();
  16. if(*iter < *(leastNumbers.begin()))
  17. {
  18. leastNumbers.erase(iterGreatest);
  19. leastNumbers.insert(*iter);
  20. }
  21. }
  22. }
  23. }

数据结构——堆(转载)相关推荐

  1. 数据结构-堆 Java实现

    数据结构-堆 Java实现. 实现堆自动增长 1 /** 2 * 数据结构-堆. 自动增长 3 * 4 * @author caiyao 5 */ 6 public class Heap<T e ...

  2. java堆 数据结构 堆_Java中的紧凑堆外结构/组合

    java堆 数据结构 堆 在上一篇文章中,我详细介绍了代码对主内存的访问方式的含义. 从那时起,我就在Java中可以做什么以实现更可预测的内存布局提出了很多疑问. 有些模式可以使用数组支持的结构来应用 ...

  3. java堆 数据结构 堆_快速堆数据结构

    java堆 数据结构 堆 In this tutorial, we'll be discussing and implementing Heap data structures in Swift. 在 ...

  4. 数据结构——堆(C++)

    数据结构--堆 文章目录 数据结构--堆 堆与堆排序 二叉树 满二叉树 完全二叉树 二叉堆 堆的存储 堆的插入删除 具体的实现 堆排序 堆与堆排序 堆(heap)分为二叉堆.二项式堆.斐波那契堆,堆是 ...

  5. 数据结构-堆(Heap)

    数据结构-堆(Heap) 我认识的堆: 1.建立在完全二叉树的基础上 2.排序算法的一种,也是稳定效率最高的一种 3.可用于实现STL中的优先队列(priority_queue)  优先队列:一种特殊 ...

  6. 数据结构--堆Heap

    数据结构:堆(Heap) 堆就是用数组实现的二叉树,所以它没有使用父指针或者子指针.堆根据"堆属性"来排序,"堆属性"决定了树中节点的位置. 堆的常用方法: 构 ...

  7. java数据结构堆_Java 数据结构-堆实现

    堆的定义:有如下性质的完全二叉树:任意节点X所处的项的关键字大于或等于以X为根的子数中的所有节点出的项的关键字. 意义在于,在数据结构中,其常常被用作优先级队列的结构,其意义是每次从队列中获取的元素, ...

  8. C语言实现常用数据结构——堆

    #include<stdio.h> #include<stdlib.h> #define CAPACITY 20/*堆有两个性质:* 1.结构性:堆必须是一颗完全二叉树* 2. ...

  9. 数据结构-堆(最大堆)

    最大堆 实质是一棵完全二叉树 每个根结点元素的值都比左右儿子的大 每次都是取出堆顶元素(可以说是优先队列) 代码 参考自浙大数据结构 #include <iostream> #includ ...

最新文章

  1. java 泛型 get()_Java泛型,get类的泛型参数
  2. Linux下CMake简明教程(八) 添加编译选项
  3. 选择海外数据中心是否等级越高越好
  4. caffe安装常见问题
  5. JDK 9:模块系统状态的重点
  6. MySQL千万数据量深分页优化
  7. extern 结构体_选三物质结构高中化学知识模块音频
  8. 经验 | 深度学习中从基础综述、论文笔记到工程经验、训练技巧
  9. 【BZOJ3172】单词,AC自动机练习
  10. C语言strcat()库函数的实现
  11. linux java sqlldr_oracle在linux如何安装sqlldr
  12. Linux之nc命令
  13. 在MySQL中,一条查询语句是如何执行的
  14. 广义典型相关分析_数学建模/机器学习:广义加性模型(GAM)及其Python实现
  15. 9. jQuery 停止动画
  16. N1刷Android TV,贫民种草指北 篇二:N1盒子:不谈刷机,只谈使用!
  17. 银行业应用系统监控的维度与目标
  18. 刚刚!蚂蚁全部互联网存款产品下架;阿里辟谣:被中央联合调查纯属谣言!...
  19. 花木兰替父从军java_花木兰替父从军 木兰诗原文
  20. Ubuntu 14.04安装bugzilla

热门文章

  1. POJ 3278 Catch That Cow
  2. 逆向分析c++ vector向量
  3. Swift怎么通过类名字符串来创建一个类
  4. HDU 6092 Rikka with Subset 思维 递推
  5. 英国推6.5亿英镑网络安全战略 强化安全屏障
  6. 钻石问题(菱形继承问题) 和虚继承
  7. SAP ECC 6.0 ,R3 windows server 2003 安装分享 自学教程
  8. android 开发使用adb操作sqlite
  9. javascript的indexOf忽略大小写
  10. [论文泛读] QoS论文两篇(Elsevier09, IEEE05)