堆是将二叉树层序遍历存储到数组中,一般用于完全二叉树,否则会造成空间的浪费
堆的分类:小根堆,每棵二叉树的根节点都小于左右孩子节点
大根堆,每棵二叉树的根节点都大于左右孩子节点
一、将二叉树调整为大根堆:
(1).调整从最后一棵子树开始
(2).没棵子树的调整都是向下调整的(如果根小,将根和孩子交换)
思路:最后一个节点的下标为len-1(len为数组的长度)
父亲节点的下标parent=(孩子节点下标-1)/2即(len-1-1)/2
找到父亲节点后parent--就可以遍历整棵树了,一边遍历一边向下调整(因为先知道父亲节点的下标)
public class TestHeap { public int[] elem;//因为堆的底层是一个数组 public int usedSize;//elem数组长度是10,有可能只传入了5个元素,因此需要一个有效长度 public TestHeap(){ this.elem=new int[10];//设置一个默认的数组容量 } /*parent为每棵树的根节点 * len为每棵树的调整结束位置 */ public void shiftDown(int parent,int len){//向下调整 int child=2*parent+1;//孩子节点下标 while(child<len){//此时孩子下标没有超过数组有效长度,证明此时至少有一个孩子 if(child+1<len&&elem[child]<elem[child+1]){//child+1<len,证明此时有两个孩子,需要找到孩子值大的那个 child++;//保证当前child为左右孩子最大值的下标 } if(elem[child]>elem[parent]){ int tmp=elem[child]; elem[child]=elem[parent]; elem[parent]=tmp; parent=child; child=2*parent+1; }else{ break; } } } public void createHeap(int[] array){//创建一个大根堆 for (int i = 0; i < array.length; i++) {//将array数组中的元素传入elem数组中 elem[i]=array[i]; usedSize++; } for (int parent = (usedSize-1-1)/2; parent >=0 ; parent--) {//找到父亲节点后parent--,遍历整棵树 shiftDown(parent,usedSize);//每次遍历都要向下调整 } } }
关于向下调整:
向下调整的循环:while(child<len)——》child下标不能越界