算法通关村14关 | 堆结构

1. 堆的概念与特征

堆是将一组数据按照完全二叉树的存储顺序,将数据存储在一维数组中的结构,对的结构有两种,一种称为大顶堆,一种称为小顶堆。

  • 小顶堆:任意节点的值均小于等于它的左右孩子,并且最小的值位于堆顶,即根节点处
  • 大顶堆:任意节点的值均大于等于它的左右孩子,并且最大的值位于堆顶,即根节点处

也可称为大根堆,小根堆,或者最大堆,最小堆,

算法通关村14关 | 堆结构_第1张图片

假设一个节点的下标为i。

  1. 当i = 0时,为根节点。
  2. 当i >= 1时,父节点为(i - 1) / 2。

有些地方叫做堆,有些地方叫做队列,两者到底是什么关系?

优先队列:就是一种队列,它的工作是poll()/peek()出队列中最大、最小的那个元素,所以叫带有优先级的队列。能够实现优先功能的队列不一定只有堆,例如二项堆、平衡树、线段树、c++会用二进制分组的vector来实现一个优先队列。

堆:堆是一个很大的概念,他并不一定是完全二叉树,用完全二叉树是因为这个容易被数组存储,但除了二叉堆之外,我们还有二项堆,斐波那契堆,这种不属于二叉树。

2. 对的构造过程

使用数组构建堆,按照层次将所有元素依次填入二叉树中,使其成为二叉树,然后不断调整,使其最终符合堆结构。

将元素依次排列到完全二叉树上去,如下图所示。

  1. int i = (size - 2) / 2 = 4(思考一下这里为什么是size-2而不是size -1)。找到数组中的4号下标。65大于其孩子,满足最大堆性质,不用交换。算法通关村14关 | 堆结构_第2张图片
  2. 然后 i = i - 1;用2和其孩子比较,2和204交换。交换之后满足最大堆,如下图左
  3. 54和其孩子比较,54和92交换,92所在子树满足最大堆,如下图右。算法通关村14关 | 堆结构_第3张图片
  4. 23和其孩子比较,23和204交换,交换完之后,23的子树却不满足了,还需要调整其子树,如下两图算法通关村14关 | 堆结构_第4张图片
  5. 12和204交换,仍然出现不平衡情况,继续调整子树。直到根节点满足要求。算法通关村14关 | 堆结构_第5张图片

这样就建成了一个大顶堆,根元素是最大的那个

3. 插入操作

插入300,将其按顺序插入到31的右孩子位置,然后不断向上爬,31<300,所以两者交换,再向上发现300比65大,交换,300>204,交换,最后就是最新堆。

算法通关村14关 | 堆结构_第6张图片

4. 删除操作

        堆中的数据特殊,对堆中数据进行的操作都是针对堆顶的元素,即每次从堆顶获取的最大值或最小值,其他的不关心,所以删除的时候,也是删除堆顶。删除堆顶整个结构会被破坏,需要再次调整。如果直接删除堆顶,群龙无首就不易管理了。实际策略是将队中的最后 一个元素与根元素交换,然后再删除堆的最后一个元素。之后再交换调最大堆,直到堆顶元素满足最大堆性质。

算法通关村14关 | 堆结构_第7张图片

交换完成之后

算法通关村14关 | 堆结构_第8张图片

关于堆的使用口诀

查找:找大用小,大的进;找小用大,小的进。

排序:升序用小,降序用大。

你可能感兴趣的:(算法通关村专栏,算法,java,数据结构)