[ 数据结构 ] 堆排序--------思路、图解、代码

news2024/11/19 14:47:03

0 基本介绍

  1. 堆定义:首先是完全二叉树,分为大顶堆和小顶堆
  2. 大顶堆:顾名思义,如果将父子节点看成一个堆(三个节点的组合),那么顶的值需要大于其两个子节点的值,即顶大;小顶堆即顶小
  3. 升序排序使用大顶堆,降序使用小顶堆
  4. 回顾顺序存储二叉树中,父子节点的关系为:下标为n的节点,它的左子节点下标(2 * n + 1),右子节点(2 * n - 1),父节点(n-1) / 2;
  5. 回顾:顺序存储二叉树
  6. 回顾:排序算法-七大内排

image-20230108130352050.png

1 思路图解

  1. 拿到n个元素的数组,就是得到了一个普通的顺序存储二叉树,也就是上面提到的普通的堆,堆大小为n
  2. 将堆调整成大顶堆,那么堆顶就是整个数组中的最大值了,将最大值和堆尾的值交换
  3. 抛开末尾的最大值,剩余的次小值构成一个大小为 n-1 的堆
  4. 对 n-1 大小的堆调整成新的大顶堆,堆顶(第二大元素产生)和该新大顶堆末尾交换,回到第3步

说明:

问:整体思路简单,就是不断构建大顶堆,首尾互换,难就难在如何调整,使得构建成满足条件的大顶堆呢?

答:编写adjust方法,用以调整当前堆(a)为大顶堆,但是该方法并不是调用一次就能完成大顶堆,举例说明:如果将父子三节点看成是一个小小堆,那么从最后一个小小堆开始,使小小堆满足父值>子值(即大顶堆的要求),从后往前对小小堆的堆顶调用adjust方法,一直到第一个小小堆,从而实现构建大顶堆

注意:第一次调整时,堆(大小为n)是完全无序的,所以需要多次调用adjust,第一次调整完毕且首尾交换后,新堆(大小为n-1)的堆顶其左右子树其实就是两个大顶堆了,所以此时只需调用一次adjust,就能完成构建大顶堆.-----------------看下面图

image-20230108152156020.png

00000000000000000000000分界线00000000000000000000000000
image-20230108153211190.png
00000000000000继续调整,交换,最终得到升序数组000000000000000000
image-20230108153401574.png

2 代码实现

//堆排序
public class App01_HeapSort {
    public static void main(String[] args) {
        int[] arr = {10, 20, 15, 25, 50, 30, 40};
        heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    //堆排序方法
    public static void heapSort(int[] arr) {
        int temp = 0;

        //从最后一个非叶子节点开始,从右往左,从下往上,调整堆,最终得到一个大顶堆
        //最后一个非叶子节点下标:arr.length / 2 - 1
        for (int i = arr.length / 2 - 1; i >= 0; i--) {
            adjust(arr, i, arr.length);
        }

        //将大顶堆的堆顶(最大值)与末尾交换,并缩减调整区间
        //调整剩余次小值的堆成为大顶堆,直到最终下标0和1交换,完成堆排序
        //问:这里j范围表示堆就一个值,为什么还要执行操作?  因为这里是先交换再调整,因为0和1需要交换,所以j需要取1,只是j=1调整方法没有生效
        for (int j = arr.length-1; j >=1; j--) {
            temp = arr[0];
            arr[0] = arr[j];
            arr[j] = temp;
            adjust(arr,0,j);
        }

    }

    //调整 堆顶为节点i的堆 为大顶堆,前提是节点i的左右子树都是大顶堆
    //问:该方法对传入的i有什么要求?
    //答:目的不同,传入i不同
    //  1.当初次构建大顶堆时,i应该从最后一个非叶子节点开始自减直到为0 (类似归并排序的先分后治)
    //  2.非初次调整时,除了堆顶,下层所有都符合上大下小,就是说目的成了将堆顶元素从上往下找位置插入构建大顶堆,所以i就是堆顶0
    public static void adjust(int[] arr, int i, int length) {
        //取出堆顶值
        int temp = arr[i];

        //从上往下寻找插入位置同时,将较大值往上挪
        for (int k = 2 * i + 1; k < length; k = 2 * k + 1) {
            //使k指向左右子节点中较小的
            if (k + 1 < length && arr[k] < arr[k + 1]) {
                k++;
            }

            //类似插值排序的移位法,就是将较大值往上挪,直到找到合适的位置插入堆顶值,从而完成构建大顶堆
            if (temp < arr[k]) {//这里为什么得用temp而不是arr[i]
                arr[i] = arr[k];
                i = k;
            //为什么这里可以break?
            //答:因为除了堆顶整体都符合上大下小,else表示堆顶比该层的节点大,即堆依然满足大顶堆,则堆无需调整
            } else {
                break;
            }
        }
        arr[i] = temp;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/148991.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java开发 - Spring框架初体验

目录 前言 了解框架的概念 Spring框架 关于Spring 在Maven中使用Spring Spring怎么管理对象 spring怎么创建对象 通过Bean注解创建对象 通过组件扫描创建对象 关于ComponentScan("xxxxxx") Spring Bean的作用域 自动装配技术 什么是自动装配 补充 Io…

MATLAB循环码编译码实验

标题循环码编译码实验一、实验目的1、掌握循环码编码原理和译码原理2、练习使用Matlab编程实现循环码编码和译码二、实验原理伴随式译码捕错译码三、实验要求1、编程实现码长n15的各种循环码的编码、译码&#xff0c;给出相应的码生成多项式、&#xff08;典型&#xff09;监督…

Java设计模式中装饰者模式/装饰者模式具体内容是什么/静态代理与装饰者模式联系与区别是什么

继续整理记录这段时间来的收获&#xff0c;详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用&#xff01; 5.4 装饰者模式 5.4.1 概述 在不改变现有对象结构的情况下&#xff0c;动态给对象增加某些职责或功能的模式 5.4.2 结构 抽象构件(Component)&#xff1a;定义…

Javascript 中的堆、栈、引用和值

学透CSS-强烈推荐 Javascript 中的内存存储 栈-Stack&#xff1a; 这是当前 Javascript 线程的暂存空间。由于 Javascript 通常只有单线程&#xff0c;因此通常只有一个堆栈。堆栈的大小也是有限的。 堆-Heap &#xff0c;它是应用程序级别的动态内存存储。从堆中访问和检索…

java 手把手带你创建一个spring入门案例

查看本文 首先 您需要下载spring 如果没有安装 可以查看我的文章 java spring下载步骤 首先 我们打开idea开发工具 选择左上角 File > New > Project 如下图操作 勾选 然后点击下一步 然后我们选择项目目录 这里我直接用了个中文目录 最好不要跟我学哦 因为个人英文不…

微信语音转换成mp3文件保存的简单详细步骤

目录 读者手册 一、前言 二、操作步骤一 把语音转化为silk文件&#xff08;silk后缀的文件&#xff09; 1.长按语音收藏&#xff08;手机操作&#xff09; 2.找到主页收藏 3.找到收藏的语音 4.转存为笔记 5.点击笔记里面的语音&#xff08;下面全部电脑操作&#xff0…

Kubernetes(k8s) 笔记总结(一)

文章目录1. 云平台2. 私有网络 VPC(重点&#xff01;&#xff01;&#xff01;)3. Kubernetes 介绍4. k8s 架构5. kubectl 和 kubeadm6. 三台云服务器的 安装部署7. Kubernetes 环境搭建7.1 安装docker环境7.2 安装k8s的 预备环境8. kubernetes集群 安装的三大件(kubelet、kube…

三句话,让Ai帮你画18万张图

本文介绍Stable Diffusion的快速上手&#xff0c;本地部署&#xff0c;以及更多有趣的玩法展示。 在 DALL-E 2 和 Imagen 之后&#xff0c;AI绘图领域又一个热乎的深度学习模型出炉——Stable Diffusion 。8月份发布的 Stable Diffusion 更加高效且轻量&#xff0c;可以在消费…

P4:Transforms的使用

transform.py就像是一个工具箱&#xff0c;里面有很多工具&#xff08;如&#xff1a;totensor、resize等不同的工具&#xff09;。 使用规则&#xff1a; 拿特定格式的图片&#xff0c;通过使用工具&#xff0c;得到想要的结果。 1、transforms.ToTensor()的使用 1、作用&a…

实战1:基于tensorflow卷积网络实现面部关键点检测详细教程(代码+数据)

项目概述: 此任务的目标是预测面部图像上的关键点位置。这可以用作多个应用程序中的构建块,例如:检测面部关键点是一个非常具有挑战性的问题。人脸特征因人而异,即使是单个人,由于 3D 姿势、大小、位置、视角和光照条件等因素也存在很大差异。 直接上结果: 数据集描…

JSP SSM 个人博客系统系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 JSP SSM 个人博客系统系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代 码和数据库&#xff0c;系统主要采…

vue3-Teleport笔记

简单来写一下Teleport src/components/TeleportLearn.vue <script setup></script><template><div><Teleport to"body"><div>你好</div></Teleport></div> </template><style scoped></style&…

NVMe IO数据传输如何选择PRP or SGL?

在Host与Controller之间有数据交互时&#xff0c;Controller会多次访问Host内存。比如执行NVMe Read/Write:当Host下发NVMe Write命令时&#xff0c;Host会先放数据放在Host内存中&#xff0c;然后通知Controller过来取数据。Controller接到信息后&#xff0c;会通过PCIe Memor…

Python下载ts文件视频并合并

目录 一、ts文件的由来 二、下载ts文件 1.下载index.m3u8&#xff0c;并做相应处理 2.下载ts文件 三、合并ts文件 一、ts文件的由来 ts文件&#xff0c;ts即"Transport Stream"的缩写&#xff0c;特点就是要求从视频流的任一片段开始都是可以独立解码的&#x…

C 程序设计教程(06)—— C 语言的运算符与表达式

C 程序设计教程&#xff08;06&#xff09;—— C 语言的运算符与表达式 该专栏主要介绍 C 语言的基本语法&#xff0c;作为《程序设计语言》课程的课件与参考资料&#xff0c;用于《程序设计语言》课程的教学&#xff0c;供入门级用户阅读。 目录C 程序设计教程&#xff08;0…

【每日一题】【LeetCode】【第七天】盛最多水的容器

解决之路 因为是周日&#xff0c;找个中等题挑战一下。 题目描述 测试案例&#xff08;部分&#xff09; 第一次 想一下&#xff0c;因为涉及到底乘高&#xff0c;所以不能排序。逆序也没必要。 简化一下题干&#xff0c;盛水最多&#xff0c;也就是算面积最大&#xff0c…

【北邮果园大三上】运筹学期中前

第一章.线性规划 1.1例题 根据现实世界中的问题建立模型 一般表达式 ①和式 ②向量式 1.2变化标准&#xff1a; 1.3线性规划求解的基础原理和单纯解法 1.3.1解 ①基础概念 基 可行解与基础解 其他分类 ②判断举例 原式子&#xff1a; 判断标准 将一个未知数作为常熟&#…

从Wireshark看TCP连接的建立与关闭

http://t.zoukankan.com/jonathanlin-p-4282582.html TCP是一种面向连接、可靠的协议。TCP连接的建立与断开&#xff0c;都是需要经过通信双方的协商。用一句话概括就是&#xff1a;三次握手say hello&#xff08;建立连接&#xff09;&#xff1b;四次握手say goodbye&#x…

蓝桥杯Python组排序算法与函数

目录 一、排序算法 二、排序函数 1、Python 的 sort() 函数和 sorted() 函数 2、sort() 例子 3、sorted() 例子 4、部分排序 三、例题 1、统计数字&#xff08;lanqiaoOJ题号535&#xff09; 2、错误票据&#xff08;lanqiaoOJ题号205&#xff09; 3、奖学金&#xf…

线程池 - ThreadPoolExecutor 详解

线程池 - ThreadPoolExecutor 详解 线程池 ThreadPoolExecutor 源码解析参考 juc 专栏系列文章。 基本概述 线程池&#xff1a;一个容纳多个线程的容器&#xff0c;容器中的线程可以重复使用&#xff0c;省去了频繁创建和销毁线程对象的操作。 线程池作用&#xff1a; 降低资…