二叉堆是特殊的完全二叉树。
定义,符合一下两点即为二叉堆:
1.是个堆
2.是个完全二叉树
因为是完全二叉树,所以一般用数组存储。
在数组中,f是父节点下标,l是左节点下标,r是右节点下标,son是子节点下标(l或者r)。
因为是完全二叉树,所以已知任何节点都能推断出它的关联节点:
(下标从0开始)
f = (son-1)/2
r = 2*f +1
l = 2*f +2
r = l +1
堆最常用于topN问题的求解。
堆的建立:
堆的建立有两种方式,一种是自底向上(bottom-top),一种是自顶向下(top-bottom)
自顶向上:
构建方法是,从堆顶节点开始,顺序的添加节点进去,每次添加到堆的最后(完全二叉树的最后一个节点后),调整节点顺序(节点依次向父节点比较大小,并调整)使其符合堆的定义。直至所有节点添加完毕,堆也就构建完成。
这种方法一般不用于构建过程,时间复杂度O(n*logn),复杂度过高。常用于动态新增节点。
自底向上:
二叉树的叶子节点数 = 二叉树的非叶子节点数 + 1
根据堆的定义,叶子节点已经符合了堆的性质,那么只需要从len/2-1(len为节点个数)处开始调整,每次调整保证当前节点符合堆的性质,直至调整至根结点。此时堆就构建完成。
时间复杂度为O(n),时间复杂度计算起来比较麻烦,此处省略。
举个例子:
节点个数为15,从15/2 -1 处,即下标为6的节点开始调整,保证它大于它的子节点(不符合则和子节点交换即可)。再调整下标为5的节点,依次类推,直到调整到下标为0的节点(根节点)。即构建完成
堆排序相对很简单:
1.建堆,采用自底向上建堆的方法即可。
2.将堆顶节点和堆的最后一个节点置换,堆长度减一,将置换后的堆顶节点进行下沉操作。
3.重复2操作,直至堆长度为0.
堆排序时间复杂度为O(n*logn) 但是常数系数较大,平均性能没有快速排序好。但是优点是时间稳定,数据量相同时排序时间最好时间和最坏时间相差不大。