堆
一、什么是堆
堆就是用数组实现的二叉树,所以它没有使用父指针或者子指针。堆根据“堆属性”来排序,“堆属性”决定了树中节点的位置。
1. 二叉树的顺序存储
2.堆的概念
- 堆逻辑上是一棵完全二叉树
- 堆物理上是保存在数组中
- 满足任意结点的值都大于其子树中结点的值,叫做大堆,或者大根堆,或者最大堆
- 反之,则是小堆,或者小根堆,或者最小堆
- 堆的作用就是找最值
二、堆的操作
- array 代表存储堆的数组
- useSize代表数组中被视为堆数据的个数
- parent代表要调整位置的下标
- child代表 parent 左孩子下标
5.child+1 代表 parent 右孩子下标
向下调整 是让调整的结点与其孩子节点进行比较,也就是根据父亲节点确定孩子节点,然后进行调整
向上调整 是让调整的结点与其父亲结点进行比较,根绝孩子节点确定父亲节点,进行调整
1. 操作-向下调整
前提:左右子树必须已经是一个堆,才能调整。
过程(以大堆为例):
- 如果已经是叶子结点(该节点的child越界),则整个调整过程结束
- 判断 index 位置有没有孩子
- 因为堆是完全二叉树,没有左孩子就一定没有右孩子,所以判断是否有左孩子(判断该节点的孩子是否越界)
- 因为堆的存储结构是数组,所以判断是否有左孩子即判断左孩子下标是否越界,即 child>useSize越界
- 确定child 或 child+1,谁是 parent的最大孩子 让child指向最大孩子
- 如果右孩子不存在,则 child就是最大child
- 否则,比较 child和child的值得大小,选择大的为 child
- 比较 parent的值 和 child的值,如果 parent>child,则满足堆的性质,调整结束
- 否则,交换 parent和child 的值
- 然后因为 child位置的堆的性质可能被破坏,所以把 child 视作 parent,向下重复以上过程
public static void adjustDown(int[] array,int parent,int useSize) {
//根据parent的位置,判定child的位置
int child = 2*parent+1;
//如果child的位置越界,则说明parent已经是叶子结点,不会进行向下调整
//child位置没有越界
while (child < useSize) {
//存在child+1,并且child的值小于child+1的值,将child指向child+1的位置,此时最大值就是child
if(child+1 <useSize && array[child] < array[child+1]) {
child++;
}
//调整的目的是为了让父节点大于子节点
//比较child和parent,如果child>parent 进行交换
//交换后,因为改变了子堆的结构,还要继续对子堆进行调整
if(array[child] > array[parent]) {
int tmp = array[child];
array[child] = array[parent];
array[parent] = tmp;
parent = child;
child = 2*parent+1;
}//其他