数据结构note9:堆排序

/**
 * 算法步骤:
 * 1.先把待排序数组A调整成最大堆
 * 把最大堆的最大值(根节点)和堆的最后一位交换,最大值是最后一位
 * 2.重复构建堆(不再包含排过序的元素),排序,直到堆的大小为1,排序结束。
 *
 * 补充:二叉树结构,也就是堆中,父节点的索引和左右儿子的节点关系如下:
 * 以数组实现,从下标0开始计算
 * parent:i
 * leftchild:2i+1
 * rightchild:2i+2
 *也可以记作是:parent = Math.floor(leftchild)或者是 parent = Math.floor(rightchild)
 * leftchild和rightchild........嗯这个就是相邻的,不用多说。[1,2],[3,4],[5,6]......
 * 二叉堆有两种:最大堆和最小堆。
 * 最大堆:每个根节点都比他的两个子节点大
 * 最小堆相反。
 */
class HeapSort {

    private static int heapSize;

    public static void main(String[] args) {
        int[] a = {7,10,5,12,8,40,15};
        heapSort(a);
        for (int i : a)
            System.out.print(i + " ");
    }

    //排序主方法
    private static void heapSort(int[] a) {
        heapSize = a.length;
        //把a调整为最大堆。
        buildMaxHeap(a);
        //每次找出堆末尾节点,把堆顶最大元素和末尾元素交换。
        for (int i = a.length - 1; i >= 1; i--) {
            swap(a, i, 0);
            heapSize = heapSize - 1;
            //继续对未排序部分调整为最大堆。
            maxHeapify(a, 0);
        }
    }

    private static void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

    //先a变成一个最大堆
    private static void buildMaxHeap(int[] a) {
        //堆化每个非子结点,最后一个非子结点=a.length/2
        for (int i = a.length / 2; i >= 0; i--) {
            //把节点i变成一个最大堆
            maxHeapify(a, i);
        }
    }

    //将a中的节点i变成一个最大堆。
    private static void maxHeapify(int[] a, int i) {
        //先把i和他的直接左右儿子节点构造成一个堆
        int l = 2 * i + 1;
        int r = 2 * i + 2;
        int largest = i;
        if (l < heapSize && a[l] > a[i])
            largest = l;
        else
            largest = i;
        if (r < heapSize && a[r] > a[largest])
            largest = r;
        if (largest != i) {
            swap(a, i, largest);
            //以上就完成了一个节点和儿子节点的比较,并且把最大值放到了堆顶。
            //但是这个堆完成后,和它交换元素的那个堆就可能发生了变化,因此需要堆largest这个节点再次进行堆化。
            maxHeapify(a, largest);
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值