一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 2 天,点击查看活动详情。
堆的基础知识
可以简单理解成他是基于完全二叉树的一种结构。
大顶堆与小顶堆
- 大顶堆: 任意三元组之间,父节点都要大于两个子节点
- 最大值:堆顶元素(所有节点的祖先)
- 第二大值:根节点的左子节点或右子节点
- 第三大值:意味着一定会有两个值大于它,在第二层或者第三层 只有父子节点之间有明确的大小关系,兄弟之间是没有明确的大小关系的
- 小顶堆:任意三元组之间,父节点都要小于两个子节点
- 最小值:根节点
堆-尾部插入调整
在最后一层的最左侧新增一个节点 == 在数组的末尾新加一个元素
看插入的节点性质是否符合堆的性质 大顶堆中:如果新增的节点大于其父节点,那么就相互替换,直到符合其性质。--- 向上调整
如下图:实现在堆尾插入一个值为13的节点
ps: 数据结构:结构定义+结构操作,定义一种性质,并且维护这种性质
堆-头部弹出调整
弹出的是堆顶元素,这时需要用尾部元素补空,然后向下调整节点,使得整个堆满足其性质。
向下调整:当前根节点是否是所在三元组中最大的一个,如果不是就与其最大的那一个替换位置,直至符合性质要求。
堆排序
如:对一个数组中的所有元素从小到大排序?
- 先对这个数组的元素进行建堆,建立成一个大顶堆
- 进行 n 轮弹堆操作
- 每次堆顶元素与堆尾元素互换位置(弹出操作:堆顶弹出,堆尾补空;只不过这个把弹出的堆顶元素放到了数组的倒数第n位)
- 然后对堆尾元素做向下调整(调整成合法的大顶堆)
- 这时刚刚弹出的这个堆顶元素所在的最后一位,其实就不属于这个堆的合法位置了,但是他还属于数组的有效空间
口诀:
1、将堆顶元素与堆尾元素交换
2、将此操作看做是堆顶元素弹出操作
3、按照头部弹出以后的策略调整堆
堆-优先队列
严谨来说,优先队列是用堆来实现的
堆是优先队列的一种实现方式