【数据结构】堆排序

堆:

  • 是具有以下性质的完全二叉树:每个节点的值都大于或等于其左右孩子节点的值,乘为大顶堆;或每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。

特点:

  • 大顶堆:arr[i] >= arr[2i+1] && arr[i] >= a[2i+2]
  • 小顶堆: arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
  • 下标从0开始。

基本思想:

  • 将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就是最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的最小值。反复执行即可得到一个有序序列。
    在这里插入图片描述
    代码实现:(大顶堆)
  • 代码实现步骤:
  • 初始化堆,自下而上,自右向左从非叶子节点开始。
    • (非叶子节点:(length-1)/2【下标从0开始】
    • 父节点:parent,左子节点=2 ×parent + 1, 右子节点=左子节点+1=2×parent + 2【下标从0开始】
  • 堆的位置调整:
    • 判断当前节点与左右子节点大小,进行位置变换,位置变换后,获取改变了位置的子节点,作为父节点继续进行比较。直到不存在子节点。
package com.zhang.Prac;

public class HeapSort {
    public static void main(String[] args) {
        int[] arr = {16, 7, 3, 20, 17, 8};

        heapSort(arr);
        for (int i : arr){
            System.out.println(i + "");
        }
    }
    //创建堆
    private static void heapSort(int[] arr){
        //创建堆
        for (int i = (arr.length - 1)/2; i >= 0; i--){
            //从第一个非叶子节点从下至上,从右至左调整结构
            adjustHeap(arr, i, arr.length);
        }
        //调整堆结构+交换堆顶元素与末尾元素
        for (int i = arr.length - 1; i >= 0; i--){
            //将堆顶元素与末尾元素进行交换
            int temp = arr[i];
            arr[i] = arr[0];
            arr[0] = temp;

            //重新对堆进行调整
            adjustHeap(arr, 0 , i);
        }
    }


    /**
     * 调整堆
     * @param arr 待排序列
     * @param parent 父节点
     * @param length 待排序列尾元素索引
     */
    private static void adjustHeap(int[] arr, int parent, int length){
        //将temp作为父节点
        int temp = arr[parent];
        //左孩子
        int lChild = 2 * parent + 1;
        while (lChild < length){
            //右孩子
            int rChild = lChild + 1;

            //如果有右孩子节点,并且右孩子节点的值大于左孩子节点,则选取右孩子节点
//            if (rChild < length){
//                System.out.println(arr[lChild] +"  "+ arr[rChild]);
//            }
            if(rChild < length && arr[lChild] < arr[rChild]){

                lChild ++;
            }
            //如果父节点的值已经大于孩子结点的值,则直接结束
            if(temp >= arr[lChild]){
                break;
            }
            //把孩子节点的值赋给父节点
            arr[parent] = arr[lChild];
            //选取孩子节点的做孩子结点,继续向下筛选
            parent = lChild;
            lChild = 2 * lChild + 1;
        }
//        System.out.println(temp);
        arr[parent] = temp;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值