说说你对堆的理解?如何实现?应用场景?

这篇具有很好参考价值的文章主要介绍了说说你对堆的理解?如何实现?应用场景?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

说说你对堆的理解?如何实现?应用场景?

一、是什么

堆(Heap)是计算机科学中一类特殊的数据结构的统称

堆通常是一个可以被看做一棵完全二叉树的数组对象,如下图:

说说你对堆的理解?如何实现?应用场景?

总是满足下列性质:

  • 堆中某个结点的值总是不大于或不小于其父结点的值
  • 堆总是一棵完全二叉树

堆又可以分成最大堆和最小堆:

  • 最大堆:每个根结点,都有根结点的值大于两个孩子结点的值
  • 最小堆:每个根结点,都有根结点的值小于孩子结点的值

二、操作

堆的元素存储方式,按照完全二叉树的顺序存储方式存储在一个一维数组中,如下图:

说说你对堆的理解?如何实现?应用场景?

用一维数组存储则如下:

[0, 1, 2, 3, 4, 5, 6, 7, 8]

根据完全二叉树的特性,可以得到如下特性:

  • 数组零坐标代码的是堆顶元素
  • 一个节点的父亲节点的坐标等于其坐标除以2整数部分
  • 一个节点的左节点等于其本身节点坐标 * 2 + 1
  • 一个节点的右节点等于其本身节点坐标 * 2 + 2

根据上述堆的特性,下面构建最小堆的构造函数和对应的属性方法:

class MinHeap {
  constructor() {
    // 存储堆元素
    this.heap = []
  }
  // 获取父元素坐标
  getParentIndex(i) {
    return (i - 1) >> 1
  }

  // 获取左节点元素坐标
  getLeftIndex(i) {
    return i * 2 + 1
  }

 // 获取右节点元素坐标
  getRightIndex(i) {
    return i * 2 + 2
  }

  // 交换元素
  swap(i1, i2) {
    const temp = this.heap[i1]
    this.heap[i1] = this.heap[i2]
    this.heap[i2] = temp
  }

  // 查看堆顶元素
  peek() {
    return this.heap[0]
  }

  // 获取堆元素的大小
  size() {
    return this.heap.length
  }
}

涉及到堆的操作有:

  • 插入
  • 删除

插入

将值插入堆的底部,即数组的尾部,当插入一个新的元素之后,堆的结构就会被破坏,因此需要堆中一个元素做上移操作

将这个值和它父节点进行交换,直到父节点小于等于这个插入的值,大小为k的堆中插入元素的时间复杂度为O(logk)

如下图所示,22节点是新插入的元素,然后进行上移操作:

说说你对堆的理解?如何实现?应用场景?

 相关代码如下:

// 插入元素
insert(value) {
  this.heap.push(value)
  this.shifUp(this.heap.length - 1)
}

// 上移操作
shiftUp(index) {
  if (index === 0) { return }
  const parentIndex = this.getParentIndex(index)
  if(this.heap[parentIndex] > this.heap[index]){
    this.swap(parentIndex, index)
    this.shiftUp(parentIndex)
  }
}

删除

常见操作是用数组尾部元素替换堆顶,这里不直接删除堆顶,因为所有的元素会向前移动一位,会破坏了堆的结构

然后进行下移操作,将新的堆顶和它的子节点进行交换,直到子节点大于等于这个新的堆顶,删除堆顶的时间复杂度为O(logk)

整体如下图操作:

说说你对堆的理解?如何实现?应用场景?

 相关代码如下:

// 删除元素
pop() {
  this.heap[0] = this.heap.pop()
  this.shiftDown(0)
}

// 下移操作
shiftDown(index) {
  const leftIndex = this.getLeftIndex(index)
  const rightIndex = this.getRightIndex(index)
  if (this.heap[leftIndex] < this.heap[index]){
    this.swap(leftIndex, index)
    this.shiftDown(leftIndex)
  }
  if (this.heap[rightIndex] < this.heap[index]){
    this.swap(rightIndex, index)
    this.shiftDown(rightIndex)
  }
}

时间复杂度

关于堆的插入和删除时间复杂度都是Olog(n),原因在于包含n个节点的完全二叉树,树的高度不会超过log2n

堆化的过程是顺着节点所在路径比较交换的,所以堆化的时间复杂度跟树的高度成正比,也就是Olog(n),插入数据和删除堆顶元素的主要逻辑就是堆化

三、总结

  • 堆是一个完全二叉树
  • 堆中每一个节点的值都必须大于等于(或小于等于)其子树中每个节点的值
  • 对于每个节点的值都大于等于子树中每个节点值的堆,叫作“大顶堆”
  • 对于每个节点的值都小于等于子树中每个节点值的堆,叫作“小顶堆”
  • 根据堆的特性,我们可以使用堆来进行排序操作,也可以使用其来求第几大或者第几小的值

参考文献

  • https://baike.baidu.com/item/%E5%A0%86/20606834
  • https://xlbpowder.cn/2021/02/26/%E5%A0%86%E5%92%8C%E5%A0%86%E6%8E%92%E5%BA%8F/

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 说说你对堆的理解?如何实现?应用场景?文章来源地址https://www.toymoban.com/news/detail-855148.html

到了这里,关于说说你对堆的理解?如何实现?应用场景?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 说说你对贪心算法、回溯算法的理解?应用场景?

    贪心算法,又称贪婪算法,是算法设计中的一种思想 其期待每一个阶段都是局部最优的选择,从而达到全局最优,但是结果并不一定是最优的 举个零钱兑换的例子,如果你有1元、2元、5元的钱币数张,用于兑换一定的金额,但是要求兑换的钱币张数最少 如果现在你要兑换

    2024年04月28日
    浏览(30)
  • 说说你对vue的mixin的理解,有什么应用场景?

    Mixin 是面向对象程序设计语言中的类,提供了方法的实现。其他类可以访问 mixin 类的方法而不必成为其子类 Mixin 类通常作为功能模块使用,在需要该功能时“混入”,有利于代码复用又避免了多继承的复杂 先来看一下官方定义 mixin (混入),提供了一种非常灵活的方式,来

    2024年03月09日
    浏览(52)
  • 说说你对slot的理解?slot使用场景有哪些?

    定义 在Vue.js中,slot(插槽)是一种用于组件之间内容分发的机制。它允许你在父组件中编写子组件的内容,从而增加了组件的灵活性和可重用性。 Slot 艺名插槽,花名“占坑”,我们可以理解为 slot 在组件模板中占好了位置,当使用该组件标签时候,组件标签里面的内容就

    2024年02月07日
    浏览(28)
  • 说说你对算法中时间复杂度,空间复杂度的理解?如何计算?

    算法(Algorithm)是指用来操作数据、解决程序问题的一组方法。对于同一个问题,使用不同的算法,也许最终得到的结果是一样的,但在过程中消耗的资源和时间却会有很大的区别 衡量不同算法之间的优劣主要是通过时间和空间两个维度去考量: 时间维度:是指执行当前算

    2024年04月09日
    浏览(26)
  • 说说对WebSocket的理解?应用场景?

    WebSocket,是一种网络传输协议,位于 OSI 模型的应用层。可在单个 TCP 连接上进行全双工通信,能更好的节省服务器资源和带宽并达到实时通迅 客户端和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输 从上图可见, websocket 服务器与客户

    2024年04月08日
    浏览(28)
  • 你对SPA单页面的理解,它的优缺点分别是什么?如何实现SPA应用呢?

    SPA(single-page application),翻译过来就是单页应用SPA是一种网络应用程序或网站的模型,它通过动态重写当前页面来与用户交互,这种方法避免了页面之间切换打断用户体验在单页应用中,所有必要的代码(HTML、JavaScript和CSS)都通过单个页面的加载而检索,或者根据需要(通

    2024年02月10日
    浏览(31)
  • 说说你对图的理解?相关操作有哪些?

    在计算机科学中,图是一种抽象的数据类型,在图中的数据元素通常称为结点, V 是所有顶点的集合, E 是所有边的集合 如果两个顶点 v , w ,只能由 v 向 w ,而不能由 w 向 v ,那么我们就把这种情况叫做一个从  v  到  w  的有向边。 v 也被称做初始点, w 也被称为终点。这

    2024年04月22日
    浏览(34)
  • 说说你对集合的理解?常见的操作有哪些?

    集合(Set),指具有某种特定性质的事物的总体,里面的每一项内容称作元素 在数学中,我们经常会遇到集合的概念: 有限集合:例如一个班集所有的同学构成的集合 无限集合:例如全体自然数集合 在计算机中集合道理也基本一致,具有三大特性: 确定性:于一个给定的

    2024年04月16日
    浏览(59)
  • 说说你对数据结构的理解?有哪些?区别?

    数据结构是计算机存储、组织数据的方式,是指相互之间存在一种或多种特定关系的数据元素的集合 前面讲到,一个程序 = 算法 + 数据结构,数据结构是实现算法的基础,选择合适的数据结构可以带来更高的运行或者存储效率 数据元素相互之间的关系称为结构,根据数据元

    2024年04月10日
    浏览(26)
  • 说说你对树的理解?相关的操作有哪些?

    在计算机领域,树形数据结构是一类重要的非线性数据结构,可以表示数据之间一对多的关系。以树与二叉树最为常用,直观看来,树是以分支关系定义的层次结构 二叉树满足以下两个条件: 本身是有序树 树中包含的各个结点的不能超过 2,即只能是 0、1 或者 2 如下图,左

    2024年04月17日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包