堆实际还是一个数组,但是我们会把它画成一个完全二叉树的样子
堆的性质:
- 堆中某个节点的值总是不大于或不小于其父节点的值;
- 堆总是一棵完全二叉树。
例子讲解
这里随便给一个乱序数组,并根据层序遍历画成二叉树的样子
{65,27,28,34,18,49,25,19,37,15}
采用向下调整,并不是从第一个元素开始向下调整,而是从下往上第一个非叶子节点开始,也就是如图的25,之后就是49,18,34,28,27,65;
调整大概就是:
找到他的左右孩子的最小的一个child,如果父节点parent小于这个child节点,就不交换,这个父节点就向下调整结束;如果父节点parent大于child就交换,此时父节点就变成子节点,再以该节点为父节点,找到他的两个孩子节点中的较小的一个,如果父节点parent小于这个child节点,就不交换,这个父节点就向下调整结束;如果父节点parent大于child就交换,以此类推;
比如图中的18,由于没有右孩子,所以15是最小的一个,又因为18大于15,所以交换;
18就变成父节点,由于此时18没有孩子节点,所以18向下调整结束;
再比如经过多次交换:
除了65都交换结束了,15与65交换,18在与65交换,27在于65交换,就此所有元素向下调整结束;
代码展示:
public void createHeap(int[] array) { int parent=(array.length-1-1)/2; while(parent>=0){ shiftDown(parent,array.length-1); parent--; } } private void shiftDown(int root,int end) { int parent=root; int child=parent*2+1; while(child<=end){ if (child + 1 <= end && elem[child+1] < elem[child]){ child++; } if(elem[child]<elem[parent]){ swap(child,parent); parent=child; child=parent*2+1; }else{ break; } } }
以此建小堆为例,尝试建一个大堆,用向下调整的方法;