堆结构及堆排序

堆结构及堆排序

前置知识

  1. 堆 是完全二叉树。
  2. 完全二叉树:如果一个树是满的,就是完全二叉树,如果一个树不满,但它处在变满的路上,且是从左往又依次变满,也叫完全二叉树,空数也算完全二叉树
  3. 数组对应成完全二叉树 :数组中 下标 i 位置 在 完全二叉树中 ,它的左孩子 : 2i +1 , 右孩子 : 2i+2, 父节点:(i-1)/2 向下取整
  4. 大根堆 :每棵子数的最大值都是头节点的值
  5. 小根堆:每棵子数的最小值都是头节点的值

堆排序(复杂度 O(NlogN))

  1. 把数组变成大根堆结构,建立堆的过程:
    1. 从上到下的方法heapInsert,时间复杂度为0(NlogN)
      2)从下到上的方法heapify,时间复杂度为O(N)
  2. 把堆的最大值和堆末尾的值交换,然后减少堆的大小之后,再去调整堆,一直周而复始,时间复杂度为O(NlogN)
  3. 堆的大小减小成0 之后,排序完成
	//从下往上,和父节点比 ,比父节点大,则和父节点交换,index来到父节点位置
    //不比父节点大 停
    private static void heapInsert(int[] arr,int index){
        while (arr[index] > arr[(index-1)/2]){ //负数 也是向上取整, index = 0 时, (index-1)/2 = 0,arr[0] > arr[0] 不满足,跳出循环
            swap(arr, index, (index-1)/2);
            index = (index-1)/2;
        }
    }
	//从上往下,和较大的子节点比,比较大的子节点小,则和较大的子节点交换 ,
    //没有子节点 或不比较大的节点小 停
    private static void heapify(int[] arr,int index, int heapSize){
        int left = 2*index +1; //左子节点的下标
        while (left < heapSize){  //完全二叉树 左节点不存在 则不可能有右节点,跳出循环,左节点存在,右节点可能存在可能不存在
            int maxIndex = 2*index + 2 < heapSize && arr[2*index +2] > arr[2*index +1] ? 2*index +2 : 2*index +1; //右节点存在切左节点的数比左节点的大,则返回右节点的下标作为子节点最大值下标,否则返回左节点
            if (arr[index] < arr[maxIndex]){
                swap(arr,index,maxIndex);
                index = maxIndex;
            }else{
                break; //不比较大的节点小 跳出循环
            }
        }
    }
public static void main(String[] args) {
        int[] arr = {2,4,7,5,4,3,1,8,2,54,32};;

        //调整成大根堆 方法1:heapInsert 复杂度O(NlogN)
        for (int i = 0; i < arr.length; i++) {
            heapInsert(arr, 0);
        }

        //调整成大根堆 方法2:heapify 复杂度O(N) 前提:必须给定了完整数组
        int heapSize = arr.length; 记录堆的长度,最开始等于数组的长度
        for (int i = arr.length -1; i >= 0; i--) {
            heapify(arr, i,heapSize);
        }

        //调整后的堆的最大值在0 位置,0 位置 和堆的最末尾位置交换,堆大小减一, 堆从0位置开始heapify调整成大根堆,循环往复,知道 堆的大小变为0
        while (heapSize > 0){
            swap(arr, 0, --heapSize);
            heapify(arr, 0,heapSize);
        }

    }
private static void swap(int[] arr,int i, int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值