前言
前段时间笔试遇到堆的问题就完全不会,所以这两天专门学习了堆,就趁还没忘做个杂乱无章的记录。
1、堆是个什么东西
首先,堆的逻辑结构是一个完全二叉树(看起来就是一个从头加到尾的二叉树),而物理结构则是一个数组。下图为一个最大堆的示例。它实际上就是[10,9,8,6,5,7]这样一个数组序列
2、堆的一些操作
(1)上浮 shift_up
顾名思义,就是把一个节点从下面浮到上面。
以上图为例,初始数据将5改为11,并对这个数据为11的节点进行上浮操作。
初始数据为[10,9,8,6,11,7]
①与父节点比较,如果比父结点大(因为当前堆为最大堆所以看谁大,最小堆就比较哪个节点比较小)则与其数据进行交换,故将9与11交换,此时数据为[10,11,8,6,9,7]
②因为与父节点比较需要到无法交换为止所以继续交换,此时11同样大于10,所以继续交换,故此时数据为[11,10,8,6,9,7]
③无法在继续交换下去了,结束
(2)下沉 shift_down
同样以上图为例,把10转变为1,初始数据为[1,9,8,6,5,7],并对这个数据进行下沉操作。
①值为1的节点与两个子节点进行比较,并且与较大的节点进行交换,更换后数据为[9,1,8,6,5,7]
②同样未到底部或者比子节点都大,继续比较,与较大的节点进行交换,更新后数据为[9,6,8,1,5,7]
(3)插入 push
往最后一个插入之后该节点它上浮
(4)弹出 pop
让根节点元素和尾节点进行交换,然后让现在的根元素下沉
(5)取顶
(取顶之前判断是否为空)
(6)堆排序
通常为筛选法
3、关于堆的一些时间复杂度
堆排序的实现复杂度 最好、最坏、平均都是O(nlogn) (空间复杂度为O(1))并且其为不稳定的排序
删除最小元素 O(logn) (小顶堆情况下) (需要调整堆)
建初堆 O(n)
合并堆 O(nlogn)
查询堆顶 O(1)