堆排序 (heapSort)(Java实现)

1.推排序需要满足的条件

  • 完全二叉树 (除了最后一层结点都在最左边,其他层(1-h-1)结点都是最大个数,只能从左向右,从上到下添加结点)
  • 父结点的值大于子结点的值(大顶堆)
  • 父结点的值小于子结点的值(小顶堆)

2.怎么构建堆

1、每次找出子结点的最大值,和父结点做交换
2、从h-1往上进行heapify

3.怎么用代码表示堆

1、可以用一维数组表示堆,int[] arr = {}; 因为它是完全二叉树,并不会断开,假如根结点从0开始,
i=4,那么父结点就是(i-1)/ 2 向下取整,子节点就是2i+1和2i+2
在这里插入图片描述

4.流程

参考链接: 添加链接描述
1、首先用无序序列构造初始堆

  • 先从最后一个非叶子结点开始,也就是h-1层,从叶子结点中找到最大值和根结点进行交换,然后接着对h-2层进行同样的处理,直到最后1层,如果由于交换,此时子根不满足大顶堆的性质的话,那么就再次进行调整。

2、然后将堆顶元素和末尾元素进行交换,接着继续调整堆(这里是从根结点开始调整),继续将堆顶元素和末尾元素交换,直到最后序列有序。

5.代码

参考链接:添加链接描述

/**
 * @author: gethin
 * @create: 2018-05-23 16:21
 * @description: 常用排序算法
 **/
public class Sort {
    public static void main(String[] args) {
        int[] nums = {16,7,3,20,17,8};
        headSort(nums);
        for (int num : nums) {
            System.out.print(num + " ");
        }
    }

    /**
     * 堆排序
     */
    public static void headSort(int[] list) {
        //构造初始堆,从第一个非叶子节点开始调整,左右孩子节点中较大的交换到父节点中
        for (int i = (list.length) / 2 - 1; i >= 0; i--) {
            headAdjust(list, list.length, i);
        }
        //排序,将最大的节点放在堆尾,然后从根节点重新调整
        for (int i = list.length - 1; i >= 1; i--) {
            int temp = list[0];
            list[0] = list[i];
            list[i] = temp;
            headAdjust(list, i, 0);
        }
    }
    
    private static void headAdjust(int[] list, int len, int i) {
        int k = i, temp = list[i], index = 2 * k + 1;
        // < len是条件,index要有边界
        while (index < len) {
            if (index + 1 < len) {
                if (list[index] < list[index + 1]) {
                    index = index + 1;
                }
            }
            if (list[index] > temp) {
            // 这里是为了调整后面的子结点
                list[k] = list[index];
                k = index;
                index = 2 * k + 1;
            } else {
                break;
            }
        }
        // 最后确定这个值在哪里
        list[k] = temp;
    }
}

时间复杂度为O(nlogn)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值