java | 堆 - 基本操作实现(1)

    科技2022-07-11  89

    概念

    堆逻辑上是一棵完全二叉树堆物理上是保存在数组中满足任意结点的值都大于其子树中结点的值,叫做大堆,或者大根堆,或者最大堆反之,则是小堆,或者小根堆,或者最小堆堆的基本作用是,快速找集合中的最值

    操作-向下调整and向上调整 目的:把一个不满足堆的结构调整成满足堆的结构 操作-建堆 下面我们给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但是还不是一个堆,现在我们通过算法,把它构建成一个堆。 根节点左右子树不是堆,我们怎么调整呢? 这里我们从倒数的第一个非叶子节点的子树开始调整,一直调整到根节点的树,就可以调整成堆。

    具体代码

    import java.util.Arrays; public class heap { //向下调整,按大堆实现(父节点值大于子节点) public static void shiftdown(int []array,int size,int index){ //array表示要处理的数组。size表示处理的数据大小,index表示从什么位置开始处理。 int parent = index; int child = parent*2 +1; //已知双亲(parent)的下标,则:左孩子(left)下标 = 2 * parent + 1; 右孩子(right)下标 = 2 * parent + 2; //已知孩子(不区分左右)(child)下标,则: 双亲(parent)下标 = (child - 1) / 2; while (child < size){ //child > size说明parent无子节点 if(child + 1 < size && array[child] < array[child+1]){ //找到子节点中较大的下标 child = child + 1; } if(array[child] > array[parent]){ // 若子节点值大于父节点值,交换。 int tem = array[child]; array[child] = array[parent]; array[parent] = tem; }else{ //否则,说明符合要求,停止当前循环 break; } parent = child; //当前的子节点重新当作父节点,继续循环 child = 2 * parent + 1; } } //向上调整,基本思路相同,不写注释 public static void shiftfup(int []array,int index){ int child = index; int parent = (child -1) /2; while (child > 0){ if(array[child] > array[parent]){ int tem = array[child]; array[child] = array[parent]; array[parent] = tem; }else {break;} child = parent; parent = (child -1) /2; } } public static void creat(int array[],int size){ //若基于向下调整建堆,则需要从后往前遍历。否则会出错 for(int i = (size-1-1)/2;i >= 0;i--){ // size-1是找到最后的叶子节点,而再-1并且除2,是找到父节点 shiftdown( array,size ,i); } } public static void main(String[] args) { int []array = {9,5,2,7,3,6,8}; creat(array,array.length); System.out.println(Arrays.toString(array)); } }

    运行:

    // 建堆前 int[] array = { 1,5,3,8,7,6 }; // 建堆后 int[] array = { 8,7,6,5,1,3 };
    Processed: 0.046, SQL: 8