堆:
通常情况下队列只是一种先进先出的结构,但是在一些情况下,我们需要考虑队列中是否有"特权"的元素,此时就应该将其放置首位或者尾部,就像我们买高铁票一样,买了商务票的进站可以不用排队,此时买商务的人就相当于将其放在了队列头的位置,初次之外,一些情况下,特权也可以将其放置尾部.
而堆其实就是数组实现的二叉树,如图所示:
首先将二叉树以层序的方式存储在一个数组当中,然后按照一定的规则向队列中添加元素,同时始终保持优先级最高的放置在数组(0)下标的位置.
二叉树中的节点父子关系对应其下标的关系:
父亲节点的下标=(左/右孩子的下标-1)/2;
左孩子的下标=(父亲下标*2+1);右孩子在左孩子的坐标上+1;
堆的性质:
1.堆的某个节点的值总是不大于或者小于其父亲节点,如下图是第一种情况,此时满足了每个节点的值总是大于等于其父亲节点,每个节点都是如此,此时根节点就是这颗树中最小的值.
2.堆总是表示的是一颗完全二叉树
如果表示非完全二叉树,那么数组在存储上就会导致空间的浪费,同时还有其他的一些…
如何创建堆
1.给定一数据的集合,如给定一个数组,根据这个数组创建堆,先别看下面的代码,这里以创建一个小根堆为例:
2.就是添加的时候向上调整建堆:对应下面的add()方法.看懂了上面,下面应该就可以理解了,同时我还在其中添加了一些其他的方法.
看一下java中自带的PriorityQueue:
部分构造方法:
一些其他的方法:
建堆的复杂度分析:
从上面的代码来看,所有的子节点都不需要向下调整,假设有n个节点,堆的高度是log2(n),从log2(n)-1层以下的所有节点可能都需要向下调整,对于每一层来说,有2^k个节点(k是当前的层数),而调整的时间复杂度是log2(k)所以每层调整的时间复杂度为k*log2(k),因此建堆的时间复杂度为:
=nlog2(n)-n;