Java实现堆排序的过程

调整堆的代码

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:

大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;
堆排序的平均时间复杂度为 Ο(nlogn)。

数据其实按照二叉树的定义相互的转换

下面是堆重建的代码

  /**
     * 对小堆进行选择重建
     * arr 是数组
     * n 是元素个数
     * i 是你期望从哪里开始把当前这个堆进行重建
     */
    public static void heapify(int arr[], int n, int i) {

        int max = i;
        int c1 = 2 * i + 1;
        int c2 = 2 * i + 2;
        if (i > n) {
            return;
        }
        if (c1 < n && arr[c1] > arr[max]) {
            max = c1;
        }
        if (c2 < n && arr[c2] > arr[max]) {
            max = c2;
        }
        if (max != i) {
            swap(arr, max, i);
            heapify(arr, n, max);
        }
    }

测试

package cn.axzo.apollo.server.util.sortUtil;

import cn.hutool.core.util.StrUtil;

/**
 * 堆排序
 *
 * @author zhuguanghong
 */
public class HeapSort {

    public static void main(String[] args) {
        int array[] = {4, 10, 3, 5, 1, 2};
        heapify(array, 6, 0);
        printArr(array);
    }

    /**
     * 对小堆进行选择重建
     */
    public static void heapify(int arr[], int n, int i) {

        int max = i;
        //左儿子的索引
        int c1 = 2 * i + 1;
        //右儿子的索引 问怎么推到来的? 要不你先背着?
        int c2 = 2 * i + 2;
        //快速返回 跳出递归
        if (i > n) {
            return;
        }
        if (c1 < n && arr[c1] > arr[max]) {
            max = c1;
        }
        if (c2 < n && arr[c2] > arr[max]) {
            max = c2;
        }
        if (max != i) {
            swap(arr, max, i);
            heapify(arr, n, max);
        }
    }

    public static void swap(int[] arr, int a, int b) {
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }

    public static void printArr(int[] arr) {
        System.out.println(StrUtil.join("-", arr));
    }
}

输出的结果: 10-5-3-4-1-2
测试结果描述

完整的构建堆

   /**
     * 从最后一个节点的父亲节点开始重建
     * @param arr 数组
     * @param n 数组长度
     */
    public static void buildHeap(int[] arr,int n){
        //得出最后一个节点的索引
        int last_node_parent = n - 1;
        //按照公式 得出他的父亲的索引
        int parent = (last_node_parent-1)/2;
        //因为节点的顺序从上到下从左到右是顺序的 所以可以从最小的堆开始重建
        for(int i =parent;i>=0;i--){
            heapify(arr,n,i);
        }
        //重建完以后堆是可以的
    }

测试结果: 10-5-3-4-1-2

对一个处理过的堆 进行排序操作

视屏讲解,懒得描述了 摸鱼时间有限

package cn.axzo.apollo.server.util.sortUtil;

import cn.hutool.core.util.StrUtil;

/**
 * 堆排序
 *
 * @author zhuguanghong
 */
public class HeapSort {

    public static void main(String[] args) {
        int array[] = {4, 10, 3, 5, 1, 2};
//        heapify(array, 6, 0);
//        buildHeap(array,6);
        headSort(array);
        printArr(array);
    }

    /**
     * 对小堆进行选择重建
     */
    public static void heapify(int arr[], int n, int i) {

        int max = i;
        int c1 = 2 * i + 1;
        int c2 = 2 * i + 2;
        if (i > n) {
            return;
        }
        if (c1 < n && arr[c1] > arr[max]) {
            max = c1;
        }
        if (c2 < n && arr[c2] > arr[max]) {
            max = c2;
        }
        if (max != i) {
            swap(arr, max, i);
            heapify(arr, n, max);
        }
    }

    /**
     * 从最后一个节点的父亲节点开始重建
     * @param arr 数组
     * @param n 数组长度
     */
    public static void buildHeap(int[] arr,int n){
        //得出最后一个节点的索引
        int last_node_parent = n - 1;
        //按照公式 得出他的父亲的索引
        int parent = (last_node_parent-1)/2;
        //因为节点的顺序从上到下从左到右是顺序的 所以可以从最小的堆开始重建
        for(int i =parent;i>=0;i--){
            heapify(arr,n,i);
        }
        //重建完以后堆是可以的
    }

    public static void headSort(int[] arr){
        int n =arr.length;
        buildHeap(arr, arr.length);
        for(int i = n-1 ;i>=0 ;i--){
            swap(arr,0,i);
            heapify(arr,i,0);
        }
    }

    public static void swap(int[] arr, int a, int b) {
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }

    public static void printArr(int[] arr) {
        System.out.println(StrUtil.join("-", arr));
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值