堆排序

对于堆排序,首先我们要清楚双亲和左右孩子的下标关系:
已知双亲下标(parent)
左孩子的下标: 2parent+1
右孩子的下标: 2
parent+2
已知左/右孩子下标
双亲下标:(child-1)/2
对堆的理解:
1.堆逻辑上是一颗完全二叉树
2.堆物理上是保存在数组中
3.满足任意结点的值都大于其子树中结点的值,叫做大堆/大根堆/最大堆,反之,小堆/小根堆/最小堆
任意给定一个数组只能逻辑上看成是二叉树,如果要看成是堆,就要建堆,大堆或者小堆都离不开向下调整的过程。
对于向下调整的操作,前提是:左右子树已经是一个堆,才能调整
说明:1.array代表储存堆的数组
2.size代表数组中被视为堆数据的个数
3.index代表要调整位置的下标
4.left代表index左孩子下标
5.right代表index右孩子的下标
代码如下:

import java.util.Arrays;
public class HeapDemo {
    //堆排序
    public static void main(String[] args) {
        int[]  array={5,2,7,4,9,7,0,6,2,1,23,15,16};
        System.out.println( Arrays.toString(array));
        int size=array.length;
        createHeapBig(array,size);
        System.out.println(Arrays.toString(array));
        createHeapSmall(array,size);
        System.out.println(Arrays.toString(array));
    }
    private static void createHeapSmall(int[] array, int size) {
        for(int i=(size-1)/2;i>=0;i--){
            shiftDown2(array,size,i);
        }
    }

    private static void shiftDown2(int[] array, int size, int index) {
        int left=2*index+1;
        while(left<size){
            int min=left;
            int right=index*2+2;
          if(right<size){//只用判断一次所以不能用while,只能用if
                if(array[right]<array[left]){
                    min=right;
                }
            }
            if(array[index]<=array[min]){
                break;
            }
            swap(array,min,index);
            //一定要检查min的堆结构是否被破坏
           index=min;
            left=2*index+1;
        }
    }

    //建大堆
    private static void createHeapBig(int[] array,int size) {
        for(int i=(size-1)/2;i>=0;i--){//从最后一个非叶子节点的子树开始调整
            shiftDown(array,size,i);
        }
    }
    private static void shiftDown(int[] array, int size,int index) {//向下调整
         int left=2*index+1;
         while(left<size){
             int max=left;
             int right=2*index+2;
             if(right<size){
                 //比较左右孩子谁是max
                 if(array[right]>array[left]){
                     max=right;
                 }
             }//走到这里找到了孩子中最大的(得到max的位置)
             //继续判断array[max]和array[index]的大小
             if(array[max]<=array[index]){
                 break;
             }
             swap(array,max,index);
             index=max;//交换完之后可能max所在的结构被破坏
             left=2*index+1;//更新left(左孩子)的值,继续循环判断
         }
    }

    private static void swap(int[] array, int max, int index) {
        int  t=array[max];
        array[max]=array[index];
        array[index]=t;
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值