目录

1、插入

2、删除

建堆

1、堆化

2、排序

与快速排序比较

堆的应用

一、优先级队列

1、合并有序小文件:

2、高性能定时器

二、求Top K和中位数

1、TopK问题

2、利用堆求中位数(动态数据)


1、堆是一个完全二叉树。(除最后一层,其他层的节点个数都是满的,最后一层的节点都靠左排列)

2、堆中一个节点的值都必须大于等于(或者小于等于)其子树中每个节点的值。对应的是大顶堆和小顶堆。

堆排序是一种原地的,时间复杂度为O(nlogn)的排序算法

大顶堆:每个节点的值都大于等于子树中每个节点值

小顶堆:每个节点的值都小于等于子树中每个节点值

堆的操作 插入与删除

1、插入

顺着节点所在的路径,向上或者向下对比(先跟最后一个数据比,依次向上),然后交换。让新插入的节点与父节点对比大小,如果满足子节点小于等于父节点,相互交换,一直重复。

2、删除

大顶堆,堆顶元素是最大元素。当我们删除堆顶元素之后,就需要把第二大的元素放到堆顶,依次迭代。直到叶子节点被删除。

问题:数组空洞,不满足完全二叉树定义。

改进 :把最后一个节点放到堆顶,然后用同样的方法比较。这就是从上往下的堆化方法。

建堆

1、堆化

从最后一个非叶子节点i = heap->elements / 2开始,使得数据满足堆的两个特性。建堆时间复杂度O(n)

void heapify(struct heap *heap, int parent)
{struct element **elem = heap->elem;int elements = heap->elements;int left, right, max;while (true) {left = parent * 2;right = left + 1;max = parent;if (left <= elements && elem[max]->data < elem[left]->data)max = left;if (right <= elements && elem[max]->data < elem[right]->data)max = right;if (max == parent)break;swap(heap, max, parent);parent = max;}
}void build_heap(struct heap *heap)
{int i;for (i = heap->elements / 2; i >= 1; i--)heapify(heap, i);
}

2、排序

按照大顶堆:数组中的第一个元素就是堆顶,我们把它跟后一个元素交换,那么最大元素就放到了下标为n的位置。再次堆化,取堆顶元素,放在n-1位置上。这样交换完数据就排序好了

void swap(struct heap *heap, int i, int j)
{struct element *tmp;tmp = heap->elem[j];heap->elem[j] = heap->elem[i];heap->elem[i] = tmp;
}int heap_sort(struct heap *heap)
{int elements = heap->elements;while (heap->elements) {swap(heap, 1, heap->elements);heap->elements--;heapify(heap, 1);}return elements;
}

排序时间复杂度 O(logn)

堆排序是不稳定的排序算法,在排序过程中,存在将堆的最后一个节点跟堆顶互换。有可能改变相同数据的原始相对顺序。

与快速排序比较

在实际开发中,为什么快速排序要比堆排序性能好

1、堆排序的数据访问方式没有快速排序友好

2、对于相同的数据,堆排序数据交换次数多余快速排序

堆的应用

一、优先级队列

队列最大特点先进先出,而优先级队列,数据的出队顺序不是先进先出,而是按照优先级来,优先级高的先出队。

堆和优先级队列非常相似,一个堆看作一个优先级队列。

1、合并有序小文件:

100个小文件,每个文件大小是100MB,每个文件中存储的都是有序的字符串。

使用优先级队列,从各文件拿出第一个string,将小文件中取出来的字符串放入到小顶堆中,100个文件的string组成的小顶堆,堆顶的元素,就是优先级队列首元素,就是最小的字符串。

将这个小字符串从堆中删除,再从小文件中取出下一个字符串,放入堆中。循环执行

时间复杂度:O(logn)

2、高性能定时器

定时器中维护很多定时任务,每个任务都设定了一个要触发执行的时间点。定时器定时扫描任务,查看任务设置的执行时间,如果到了,就拿出来执行。

每过1秒扫描一遍任务列表做法低效

1、任务定时可能很久,1s扫描很多都是徒劳

2、每次都扫描整个任务列表,如果任务表很大,必然会很耗时。

使用优先级队列

按照任务设定的执行时间,将这些任务存储在优先级队列中,队列首部存储的是最先执行的任务。

拿队首任务的执行时间点,与当前时间相减,得到时间间隔T;T就是需要等待多久。

时间到,从队首取出任务,然后再计算新的任务执行时间与当前时间点的差值。

二、求Top K和中位数

1、TopK问题

1、静态数据,数据事先确定,不会改变

维护一个大小为K的小顶堆,顺序遍历数组,从数组中取出数据与堆顶元素比较。如果比堆顶元素大,把堆顶元素删除,并且将这个元素插入到堆中;

如果比堆顶元素小,则不做处理。等数据都遍历完后,堆数据就是前K大数据。

时间复杂度:遍历数组O(n)时间复杂度,一次堆化操作需要O(logk)的时间复杂度,最坏情况下,n个元素都入堆一次,时间复杂度O(nlogk)

2、动态数据

两个操作:1、添加数据;2、询问当前的K大数据

一直维护一个K大小的小顶堆

当有数据添加到集合中,拿堆它与堆顶元素对比。如果比堆顶元素大,就把堆顶元素删除,并将这个元素加入到堆中;如果比堆顶元素小,不变。

无论任何时候都需要查询当前的K大数据,都可以得到。

时间复杂度:如果每次询问前K大数据,基于当前的数据重新计算的话,时间复杂度O(nlogk),n表示当前数据的大小。

2、利用堆求中位数(动态数据)

先将数据排序,再将数据一分为二,维护两个堆,一个大顶堆,一个小顶堆

当有数据插入时,如果数据小于等于大顶堆的元素,就将这个数据添加到大顶堆中;否则,小顶堆。

调整:数据插入,破坏了数据均分的特性;将一个堆顶元素,移动到另一个堆中。

插入数据涉及堆化,时间复杂度为O(logn),查找时间复杂度O(1)

数据结构与算法—堆(heap)相关推荐

  1. 数据结构与算法---堆的基本操作

    堆的定义 堆可以看做是一种特殊的树,堆结构满足两个条件: 1.堆是一个完全二叉树. 2.堆的每一个节点的值都大于等于(或小于等于)其子节点的值. 大于等于子节点的值我们叫它:大顶堆 小于等于子节点的值 ...

  2. 数据结构与算法 | 堆

    二叉树的顺序结构 堆的概念及结构 堆的实现 二叉树的顺序结构 普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费.而完全二叉树更适合使用顺序结构存储.现实中我们通常把堆(一种二叉树)使用 ...

  3. 数据结构与算法——堆的原理和实现

    目录 一.堆的原理 二.堆的实现 1.堆的定义 2.堆的初始化 3.向上调整算法 4.向上调整算法代码实现 5.堆的插入 6.向下调整算法 6.堆的删除 7.堆的大小 8.判断堆是否为空 总结 一.堆 ...

  4. 数据结构与算法(6) -- heap

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

  5. 数据结构与算法 / 堆结构

    一.基本信息 1.本质 一颗特殊的树. 2.特性 完全二叉树. 堆中每一个节点的值都必须大于等于(或小于等于)其子树中每个节点的值. 3.分类 对于每一个节点的值都大于等于子节点的值的情况,该堆被称为 ...

  6. 算法与数据结构基础 - 堆(Heap)和优先级队列(Priority Queue)

    堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值: 图片来源:这里 堆可以用数组存储,插入.删除会触发节点shift_down.shif ...

  7. codeforces 贪心+优先队列_算法与数据结构基础 - 堆(Heap)和优先级队列(Priority Queue)...

    堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值:

  8. 数据结构与算法(4)——优先队列和堆

    前言:题图无关,接下来开始简单学习学习优先队列和堆的相关数据结构的知识: 前序文章: 数据结构与算法(1)--数组与链表(https://www.jianshu.com/p/7b93b3570875) ...

  9. 数据结构之堆Heap

    1. 概述 堆(也叫优先队列),是一棵完全二叉树,它的特点是父节点的值大于(小于)两个子节点的值(分别称为大顶堆和小顶堆).它常用于管理算法执行过程中的信息,应用场景包括堆排序,优先队列等. 2. 堆 ...

最新文章

  1. 用C语言实现控制台模拟显示时
  2. Java开发怎么达到年薪 50w ?我有一些想法和建议
  3. WCF异常:HTTP 无法注册,另一应用程序正在使用 TCP 端口 80
  4. Anaconda-- conda 创建、激活、退出、删除虚拟环境
  5. Oracle到出dmp
  6. docker中lnmp访问php页面,Docker下部署LNMP工作环境的教程(详细步骤)
  7. linux日志分析与痕迹清理
  8. Blend4开发:会飞的小鸟
  9. linux软件包管理 pdf,vSphere Storage Appliance 安装和管理 PDF
  10. 在SharePoint网站中访问Webservice被拒绝的解决方法
  11. HTTP / HTTPS抓包工具-Fiddler
  12. 微信小程序实例源码大全
  13. 软件设计师历年真题(链接在文末)
  14. 通过有限差分和matlab矩阵运算直接求解一维薛定谔方程,通过有限差分和MATLAB矩阵运算直接求解一维薛定谔方程...
  15. 怎样开启Win7快速启动栏以及怎样显示右下角运行程序通知
  16. Visual Studio使用技巧 +谷歌浏览器使用技巧总结
  17. 字体大小fontsize中的pt、px、em
  18. windows安全事件ID编号解释大全
  19. Airbnb(爱彼迎)产品分析报告
  20. python 路径格式化_吐血整理!140种Python标准库、第三方库和外部工具都有了!...

热门文章

  1. mtk6595资料帖和问题帖集合
  2. Hi-End音箱真伪(3)-巴汉著文
  3. 网络协议栈TSO/UFO/GSO/LRO/GRO/RSS特性
  4. python爬取王者_用Python爬取王者农药英雄皮肤
  5. jmeter 压测java代码
  6. 无能狂怒之@RequestParam、@PathParam、@PathVariable三者有什么区别我都不知道!
  7. 加快数字创新赋能实体经济 CDEC2021中国数字智能生态大会成都站今日举行
  8. 一位老先生对年轻人不得不说的十大忠告〔转〕
  9. linux克隆tf卡中的内容,TF/SD内存卡数据克隆怎样做图文详细教程
  10. JSON简介:什么是JSON?