LeetCode刷题(七)——堆

堆的定义

堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树数组对象。
这里涉及到一个概念,即完全二叉树。
完全二叉树是二叉树的一种特殊的形式,下面是来自百度百科对完全二叉树的释义:一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。
这里面又涉及到满二叉树的定义:满二叉树就是二叉树每一层的结点个数都达到了最大值, 即第i层上有2^i-1 个结点
下面给出我自己对完全二叉树的理解:
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。如下图所示就是一颗完全二叉树,图中树的深度为4,除了第4层,其他三层都达到了最大的节点数,第4层的节点也在最左边,所以它是一颗完全二叉树。
在这里插入图片描述

堆的类型

根据堆的性质之一——堆中某个节点的值总是不大于或不小于其父节点的值,可以将堆分为大根堆(最大堆)与小根堆(最小堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
注:堆的根节点中存放的是最大或者最小元素,但是其他节点的排序顺序是未知的。

堆的基本操作

  • 上浮 shift_up
  • 下沉 shift_down
  • 插入 push
  • 弹出 pop
  • 取顶 top
  • 堆排序 heap_sort

堆的算法思想

假设现在有一个小根堆,并且根的元素名为root ,其左右子节点为leftright ,此时插入一个新的元素,这种情况下,有两种可能:
(1)root<=left 并且root<=right,即根节点比它的左右子节点都小,则说明此时就是最小堆;
(2)root>left或者root>right ,此时root应与两个左右子节点中值较小的一个交换,结果得到一个堆,这个时候,如果root的值仍然大于其新的左右节点的一个或全部的两个的值,则重复上一步操作,继续和新的左右子节点中较小的值交换,即之前提到的堆的基本操作中的下沉操作(如果是最大堆则情况相反,相应的就是上浮操作)。重复这个过程,直至到达某一个层使它小于它所有子节点,或者它成了叶子结点。

堆的应用

根据前面堆的性质,我们知道堆的根节点存放的一组数据中最大或者最小的元素。所以堆经常用来解决TOPK问题。比如LeetCode中的 前 K 个高频元素数组中的第K个最大元素等。
还有比如:如何从100万个数中找出最大的前100个数。我们可以先取出前100个数,对这100个数构建一个最小堆。然后遍历一遍剩余的元素,在此过程中维护这个最小堆就可以了。
步骤:

  • 取前m个元素(例如m=100),建立一个小顶堆
  • 顺序读取后续元素,直到结束。每次读取一个元素,如果该元素比堆顶元素小,直接丢弃
    如果大于堆顶元素,则用该元素替换堆顶元素,然后保持最小堆性质。
  • 最后这个堆中的元素就是前最大的100个。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值