zoukankan      html  css  js  c++  java
  • 浅谈对顶堆

    对顶堆详解

    我们知道,堆是一种极有用的数据结构。它能在短时间内将数据维护成单调递增/递减的序列。但是这种“朴素堆”对于问题求解起到的效果毕竟是有限的。所以我们在朴素堆的基础上,进行深入思考和适当变形,使之能解决一些其他的用朴素堆解决不了的问题,并使思路变得简洁有效。

    这篇随笔就堆中的一个分支——对顶堆进行讲解,读者在阅读前应该掌握堆的基本概念,以便于更好地理解对顶堆。

    如果把堆中的大根堆想成一个上宽下窄的三角形,把小根堆想成一个上窄下宽的三角形,那么对顶堆就可以具体地被想象成一个“陀螺”或者一个“沙漏”,通过这两个堆的上下组合,我们可以把一组数据分别加入到对顶堆中的大根堆和小根堆,以维护我们不同的需要。

    那么对顶堆是干嘛用的呢?

    举一个例题:

    给定(N)个数字,求其前(i)个元素中第(K)小的那个元素。

    我们很容易想到用堆来维护这个单调递增的序列,如果使用数组实现的话,我们直接输入数组下标为(K)的元素即可。但我们使用的是堆,它的实现方式——优先队列是不支持任意点访问的,那么我们就无法进行单点查询。引申对顶堆的概念,我们可以这样解决问题:

    优先队列虽然不支持任意点访问,但可以用(O(1))的时间查询出堆顶元素,也就是说,我们只能通过维护对顶堆中两个堆的堆顶元素来进行单调性的维护。怎么办呢?

    原理很简单:根据数学中不等式的传递原理,假如一个集合(A)中的最小元素比另一个集合(B)中的最大元素还要大,那么就可以断定:(A)中的所有元素都比(B)中元素大。所以,我们把小根堆“放在”大根堆“上面”,如果小根堆的堆顶元素比大根堆的堆顶元素大,那么小根堆的所有元素要比大根堆的所有元素大。

    回到这个问题:我们要求第(K)小的元素,那么我们把大根堆的元素个数限制成(K)个,前(K)个元素入队之后,每个元素在入队之前先与堆顶元素比较,如果比堆顶元素大,就加入小根堆,如果没有的话,把大根堆的堆顶弹出,将新元素加入大根堆。这样就维护出一个对顶堆。它的作用在于找出第(K)小的元素

    同理,对顶堆还可以用于解决其他“第(K)小”的变形问题:比如求前(i)个元素的中位数等。

  • 相关阅读:
    vue使用watch 观察路由变化,重新获取内容
    Intellij IDEA 最新旗舰版注册激活破解(2018亲测,可用)
    前端开发浏览器兼容问题
    基于Docker搭建MySQL主从复制
    js获取计算后的样式表
    js对象取值的两种方式
    js中的style与jQuery中的css
    js页面加载函数
    代码中jndi数据源的支持
    Oracle中的sid与servicename
  • 原文地址:https://www.cnblogs.com/fusiwei/p/11432323.html
Copyright © 2011-2022 走看看