堆排序算法剖析

1.将待排序列以一个完全二叉树存储,设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层所有的结点都连续集中在最左边,这就是完全二叉树。

堆排序算法剖析

2.第一趟排序,从二叉树的最后一个根节点(有步骤1可知是值为12的节点)开始,调整当前节点所在的堆,使当前节点大于所有子节点的值,最终得到的堆是最大根堆。

(1)12->36

堆排序算法剖析

(2)73->81

堆排序算法剖析

(3)49->98

堆排序算法剖析

(4)55->81->73

堆排序算法剖析

(5)40->98->49

堆排序算法剖析

3.第二趟排序,每趟排序后,待排序列中的最大值将被移动到根节点,将根节点元素与待排序列中最后一个元素交换位置,红色元素表示已经排好的序列,红色元素不参与下轮的排序过程

(1)98->12

堆排序算法剖析

(2)12->81->73->64

堆排序算法剖析

(3)81->12

堆排序算法剖析

(4)12->73->64->55

堆排序算法剖析

(5)73->12

堆排序算法剖析

(6)12->64->55

堆排序算法剖析

(7)64->40

堆排序算法剖析

(8)40->55

堆排序算法剖析

(9)55->27

堆排序算法剖析

(10)27->49

堆排序算法剖析

(11)49->36

堆排序算法剖析

(12)36->40

堆排序算法剖析

(13)40->12

堆排序算法剖析

(14)12->36

堆排序算法剖析

(15)36->27

堆排序算法剖析

(16)27->12

堆排序算法剖析

(16)12->12

堆排序算法剖析

代码:

package com.zjl.tool.sort;

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

    /**
     * @param args
     */
    public static void main(String[] args) {
        int[] arr = {40,55,49,73,12,27,98,81,64,36};//待排序数组
        HeapSort(arr, arr.length - 1);//将arr按照降序排列
        //打印排序后的数组
        for(int value : arr) {
            System.out.print(value + " ");
        }
    }

    /**
     * 待排序列(R1,R2,...,Rk,...Rn)看作是完全二叉树,通过比较、交换,父节点和孩子节点的值,
     * 使得对于任意元素Rk(k=R(2k),Rk>=R(2k+1)
     * @param arr    数组对象
     * @param start    数组的开始下标
     * @param end    数组的结束下标
     */
    private static void HeapAdjust(int[] arr, int start, int end) {
        //当下标为start的元素有孩子元素时
        while(start ) {
            //left和right分别为左右孩子元素的下标,max为左右孩子中值较大的孩子的元素下标
            int left = 2 * start+1;
            int right = 2 * start+2;
            int max = 0;

            //如果既有左孩子,又有右孩子
            if(left < end&&right  end) {
                //如果左孩子小于右孩子的值,max = right,否则为max = left
                if(arr[left]  arr[right])
                    max = right;
                else
                    max = left;
            }
            //如果只有左孩子,没有右孩子,max值为left
            if(left  end) {
                max = left;
            }
            //如果没有孩子,则表明到了完全二叉树的叶子节点
            if(left > end) {
                break;
            }

            //如果当前节点值小于两孩子中的值较大者,那么将当前节点值与max交换
            if(arr[start] < arr[max]){
                int tmp = arr[start];
                arr[start] = arr[max];
                arr[max] = tmp;
            }
            //当前节点向孩子节点迭代
            start = max;
        }
    }

    /**
     * @param arr 数组
     * @param end    数组结束下标
     */
    private static void HeapSort(int[] arr, int end) {
        //由最后一个非叶子节点,向根节点迭代,创建最大堆,数组中的最大值将被移动到根节点
        for(int start = end/2;start >= 0;start--) {
            HeapAdjust(arr, start, end);
        }

        while(end > 0){
            //交换arr[0]和arr[end]的值
            int tmp = arr[0];
            arr[0] = arr[end];
            arr[end] = tmp;

            //排序范围变为(0,end-1)
            HeapAdjust(arr, 0, end - 1);
            end--;
        }
    }

}

Original: https://www.cnblogs.com/huanongying/p/7622168.html
Author: 花弄影
Title: 堆排序算法剖析

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/622006/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Micrometer + Prometheus 监控 Feign 调用实战

    可观测性是系统架构的基石,准确详细的度量是工程师的重要决策来源。对于微服务系统,除了传统意义上系统边界层的监控指标,服务内部调用的情况也需引起重视,这回就来分享下笔者在实现Feig…

    Java 2023年6月5日
    075
  • Thymeleaf小记

    最近学习javaweb 之前将很多的学习时间都用在了jsp 和 JQREY 的学习上,但是最近发现已经过时了,本来想学好后做项目的但是发现过时后很伤心,想做项目的心已经凉了,作为代…

    Java 2023年6月8日
    062
  • JDK下载、安装与环境配置

    一、JDK下载与安装 1.1、下载JDK安装包 博主在这里给大家准备了一个64位操作系统的jdk1.8以便大家下载(使用的是迅雷)点击此处下载提取码:dfbt 如果其他小伙伴的电脑…

    Java 2023年6月5日
    069
  • java: You aren’t using a compiler supported by lombok, so lombok will not work and has been disabled

    idea 报错:java: You aren’t using a compiler supported by lombok, so lombok will not wo…

    Java 2023年5月29日
    048
  • springcloud整合nacos配置中心

    最近实物资产管理运维产品pams系统架构搭建中,涉及到配置中心的问题,在这里做个记录,作为第一手经验分享,也是自我备忘吧。 整个体系,目前一共有10+个中等粒度的微服务,每个服务都…

    Java 2023年5月30日
    095
  • 动态线程池框架 DynamicTp v1.0.7版本发布。还在为Dubbo线程池耗尽烦恼吗?还在为Mq消费积压烦恼吗?

    DynamicTp 简介 DynamicTp 是一个基于配置中心实现的轻量级动态线程池管理工具,主要功能可以总结为 动态调参、通知报警、运行监控、三方包线程池管理等几大类。 经过几…

    Java 2023年6月14日
    091
  • HTML基础笔记整理

    「学习笔记」HTML基础 勤做笔记不仅可以让自己学的扎实,更重要的是可以让自己少走弯路。有人说:”再次翻开笔记是什么感觉”,我的回答是:”初恋般…

    Java 2023年6月7日
    071
  • docker容器编排原来这么丝滑~

    前言: 请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i 概念介绍: Docker 这个东西所扮演的角色,容易理解,它是一个容器引擎,也就是说实际上我们的容器最终是由Doc…

    Java 2023年6月5日
    067
  • 字节码&ASM-基础

    在接触ASM之前不得不去了解一些字节码相关的前置知识,掌握字节码的类型描述、JVM代码执行模型是开启ASM大门的钥匙,掌握这把钥匙开启大门才能走上一条康庄大道通往ASM,否则一路摸…

    Java 2023年6月7日
    057
  • JAVA不可变List的实现

    有时候方法返回一个列表但是不想调用者改变列表内容。有三种方法可以实现不可变列表,通过调用JDK,Guava以及Apache Commons Collections相关API来实现。…

    Java 2023年5月29日
    065
  • MSSQL·FOR XML PATH语法转义尖括号解决方案

    阅文时长 | 0.14分钟字数统计 | 225.6字符主要内容 | 1、引言&背景 2、示例及解决方案 3、声明与参考资料『MSSQL·FOR XML PATH语法转义尖括…

    Java 2023年6月5日
    073
  • Windows安装使用Chocolatey 包软件管理(类似 rpm , yum, brew , apt-get 包管理器工具)

    Windows也能像Linux或者Mac那样命令行安装管理软件了,,,真的太方便了 *下载安装 使用window powershell 用管理员运行 Set-ExecutionPo…

    Java 2023年6月15日
    083
  • Final

    final 基本介绍: final可以修饰类、属性、方法和局部变量 下面情况下可能会用到final 当不希望类被继承时,可以用final修饰; 当不希望父类的某个方法被子类覆盖/重…

    Java 2023年6月5日
    069
  • 入学体检—二甲及二甲以上医院

    终于可以去一所一本院校再读两年书。于2022年4月6日体检。现将体检过程分享给网友。 先是在学校官网下载体检表,第二天去的一家三甲医院。 在哔哩哔哩上看了一眼体检注意事项。 如果有…

    Java 2023年6月5日
    054
  • Redis 哈希Hash底层数据结构

    Redis 底层数据结构 Redis数据库就像是一个哈希表,首先对key进行哈希运算得到哈希值再取模得到一个下标,每个元素是一个节点,节点之间形成链表。这感觉有点像Java中的Ha…

    Java 2023年6月7日
    069
  • Typora中Markdown学习

    可以自己设置标题级数,且各标题之间可在大纲处看到鲜明的层级关系,非常方便清楚。 “#”——一级标题 “##”——二级标题 &#822…

    Java 2023年6月5日
    0198
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球