宝藏速成秘籍(7)堆排序法

一、前言

1.1、概念

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

 1.2、排序步骤  

  1. 构建最大堆(或最小堆):将待排序的数组构建为一个最大堆(或最小堆)。这可以通过从数组末尾开始,依次将每个节点调整到合适的位置来实现。调整的方法是将当前节点与其父节点比较,如果当前节点大于(或小于)父节点,则交换它们的位置,并重复这个过程直到当前节点符合最大堆(或最小堆)的性质。

  2. 交换堆顶和末尾元素:将最大堆(或最小堆)的堆顶元素与数组的最后一个元素交换位置。

  3. 破坏堆性质:将数组末尾的元素从堆中移除,即将数组的长度减一,并且将堆的根节点进行一次调整,使得剩余元素仍然满足最大堆(或最小堆)的性质。

  4. 重复步骤2和步骤3,直到堆的大小为1,即只剩下一个元素。

  5. 排序完成:最后得到的数组就是一个有序序列。

二、方法分析

       堆排序是一种基于堆数据结构的比较排序算法。堆是一种完全二叉树,分为最大堆和最小堆。在最大堆中,每个节点的值都大于或等于其子节点的值;在最小堆中,每个节点的值都小于或等于其子节点的值。堆排序通常使用最大堆进行升序排序。堆排序分为两个主要步骤:构建堆和排序。

三、举例说明 

对数组 `[4, 10, 3, 5, 1]` 进行堆排序

#### 步骤 1:构建最大堆

将数组视为一个完全二叉树,然后从最后一个非叶子节点开始,向前调整每个节点,使其符合最大堆的性质。

1. 初始数组: `[4, 10, 3, 5, 1]`
   - 二叉树表示:  

         4
        / \
       10  3
      /  \
     5    1

2. 从最后一个非叶子节点开始调整(节点 `10`,索引 `1`)。
   - 节点 `10` 已经大于它的子节点,所以不需要调整。

3. 调整节点 `4`(索引 `0`)。
   - 节点 `4` 的子节点为 `10` 和 `3`。由于 `10` 最大,将 `4` 和 `10` 交换。
   - 调整后数组: `[10, 4, 3, 5, 1]`
   - 二叉树表示:

         10
        / \
       4   3
      / \
     5   1

- 继续调整节点 `4`。它的子节点为 `5` 和 `1`,将 `4` 和 `5` 交换。
   - 调整后数组: `[10, 5, 3, 4, 1]`
   - 二叉树表示:
    

         10
        / \
       5   3
      / \
     4   1

现在,我们已经构建了一个最大堆。

#### 步骤 2:排序

将堆顶元素(最大值)与堆的最后一个元素交换,然后将剩余元素重新调整为最大堆,重复该过程直到所有元素有序。

1. 交换 `10` 和 `1`,并调整剩余部分为最大堆。
   - 调整后数组: `[1, 5, 3, 4, 10]`
   - 重新调整:

         1
        / \
       5   3
      /
     4

 - 节点 `1` 的子节点为 `5` 和 `3`,将 `1` 和 `5` 交换。
   - 调整后数组: `[5, 1, 3, 4, 10]`
   - 继续调整节点 `1`,将 `1` 和 `4` 交换。
   - 调整后数组: `[5, 4, 3, 1, 10]`
   - 二叉树表示:

         5
        / \
       4   3
      /
     1

2. 交换 `5` 和 `1`,并调整剩余部分为最大堆。
   - 调整后数组: `[1, 4, 3, 5, 10]`
   - 重新调整:

         1
        / \
       4   3

   - 节点 `1` 的子节点为 `4` 和 `3`,将 `1` 和 `4` 交换。
   - 调整后数组: `[4, 1, 3, 5, 10]`
   - 二叉树表示:

         4
        / \
       1   3

3. 交换 `4` 和 `3`,并调整剩余部分为最大堆。
   - 调整后数组: `[3, 1, 4, 5, 10]`
   - 重新调整:

         3
        / 
       1

  - 节点 `3` 的子节点为 `1`,不需要调整。

4. 交换 `3` 和 `1`。
   - 调整后数组: `[1, 3, 4, 5, 10]`
   - 重新调整:没有需要调整的部分。

最终,数组变为有序的 `[1, 3, 4, 5, 10]`。

通过上述步骤,堆排序成功地对数组进行了升序排列。

四、编码实现 

 下面是用Java实现的堆排序算法:

public class HeapSort {
    public static void main(String[] args) {
        int[] arr = {4, 10, 3, 5, 1};
        heapSort(arr);
        System.out.println("排序后的数组:");
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }

    public static void heapSort(int[] arr) {
        // 构建大顶堆
        for (int i = arr.length / 2 - 1; i >= 0; i--) {
            adjustHeap(arr, i, arr.length);
        }
        // 调整堆结构+交换堆顶元素与末尾元素
        for (int j = arr.length - 1; j > 0; j--) {
            swap(arr, 0, j);
            adjustHeap(arr, 0, j);
        }
    }

    public static void adjustHeap(int[] arr, int i, int length) {
        int temp = arr[i]; // 先取出当前元素i
        for (int k = i * 2 + 1; k < length; k = k * 2 + 1) { // 从i结点的左子结点开始,也就是2i+1处开始
            if (k + 1 < length && arr[k] < arr[k + 1]) { // 如果左子结点小于右子结点,k指向右子结点
                k++;
            }
            if (arr[k] > temp) { // 如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
                arr[i] = arr[k];
                i = k;
            } else {
                break;
            }
        }
        arr[i] = temp; // 将temp值放到最终的位置
    }

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

 五、方法评价 

  1. 时间复杂度:堆排序的时间复杂度是O(nlogn),其中n是待排序数组的长度。构建堆的时间复杂度是O(n),每次调整堆的时间复杂度是O(logn),共需要进行n-1次调整。因此,总的时间复杂度为O(nlogn)。

  2. 空间复杂度:堆排序的空间复杂度为O(1),即不需要额外的空间进行排序。

  3. 稳定性:堆排序是一种不稳定的排序算法。在交换堆顶和末尾元素的过程中,可能会改变相同元素的相对顺序。

  4. 原地排序:堆排序是一种原地排序算法,即不需要额外的辅助空间。

 结语 

容易实现的那不叫梦想

轻言放弃的算不上努力

想成功,先发疯,不顾一切向前冲

!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Uni-App中的u-datetime-picker时间选择器Demo

目录 前言Demo 前言 对于网页端的推荐阅读&#xff1a;【ElementUI】详细分析DatePicker 日期选择器 事情起因是两个时间选择器同步了&#xff0c;本身是从后端慢慢步入全栈&#xff0c;对此将这个知识点从实战进行提炼 通过Demo进行总结 Demo 用于选择日期和时间的组件&a…

zookeeper介绍 和 编译踩坑

zookeeper 分布式协调服务 ZooKeeper原理及介绍 - 鹿泉 - 博客园 Zookeeper是在分布式环境中应用非常广泛&#xff0c;它的优秀功能很多&#xff0c;比如分布式环境中全局命名服务&#xff0c;服务注册中心&#xff0c;全局分布式锁等等。 本项目使用其分布式服务配置中心&am…

Java--数组的使用

1.普通For循环&#xff08;用的最多&#xff0c;需从中取出数据以及下标&#xff09; eg&#xff1a;图中三类问题都可 2.For-each循环&#xff08;一般用来打印一些结果&#xff09; eg&#xff1a;打印数组的具体元素 3.数组作方法入参&#xff08;对数组进行一些操作&#x…

【实例分享】银河麒麟高级服务器操作系统环境资源占用异常-情况分析及处理方法

1.情况描述 使用vsftp进行文件传输&#xff0c;发现sshd进程cpu占用异常&#xff0c;并且su和ssh登录相比正常机器会慢2秒左右。 图&#xff11; 2.问题分析 通过strace跟踪su和sshd进程&#xff0c;有大量ssh:notty信息。 图2 配置ssh绕过pam模块认证后&#xff0c;ssh连接速…

外观模式(大话设计模式)C/C++版本

外观模式 C #include <iostream> using namespace std;class stock1 { public:void Sell(){cout << "股票1卖出" << endl;}void Buy(){cout << "股票1买入" << endl;} };class stock2 { public:void Sell(){cout <<…

C++设计模式——Decorator装饰器模式

一&#xff0c;装饰器模式简介 装饰器模式是一种结构型设计模式&#xff0c; 它允许在不改变现有对象的情况下&#xff0c;动态地将功能添加到对象中。 装饰器模式是通过创建具有新行为的对象来实现的&#xff0c;这些对象将原始对象进行了包装。 装饰器模式遵循开放/关闭原…

AI办公自动化:批量在多个Word文档中插入对应图片

工作任务&#xff1a;文件夹中有多个word文档和word文档名称一致的图片&#xff0c;要把这些图片都插入到word文档中 在chatpgt中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;写一个Python脚本&#xff0c;具体步骤如下&#xff1a; 打开文件夹&#xff1a;F:…

c++/c输出double问题

这个我大抵能理解&#xff0c;%d是int嘛。 这是为啥&#xff1f; 这样又好了&#xff1f; 这我也能理解 这也可以 这也对&#xff1f; &#xff08;我知道我呢个函数为什么不对了&#xff0c;我的函数写的是int(&#xff09;) 附&#xff1a;保留几位小数&#xff1a; %.2f

手把手教你入门vue+springboot开发(三)--登录功能后端

文章目录 前言一、redis安装二、后端代码1.修改application.yml文件2.增加utils文件3.增加Result类4.修改UserController类5.修改UserMapper类6.修改UserService和UserServiceImpl类7.增加LoginInterceptor类8.增加WebConfig类9.修改pom.xml文件 前言 前两篇我们用vuespringbo…

基于负相关误差函数的4集成BP神经网络matlab建模与仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 MATLAB2022a 3.部分核心程序 ...............................................................…

XILINX 7系列XDMA使用_IP核介绍以及工程搭建

文章目录 一、XDMA IP核1.1、接口说明1.2、配置页说明 二、XDMA工程搭建2.1、BD搭建2.2 Linux下XDMA驱动安装2.3 Linux下使用XDMA进行数据传输 一、XDMA IP核 1.1、接口说明 sys_clk&#xff1a;主机给PCIE提供的时钟信号&#xff0c;通过原理图查看 sys_rst_n&#xff1a;主机…

宠物健康顾问系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;顾问管理&#xff0c;用户管理&#xff0c;健康知识管理&#xff0c;管理员管理&#xff0c;论坛管理&#xff0c;公告管理 顾问账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;顾…

宝藏速成秘籍(3)选择排序法

一、前言 1.1、概念 选择排序法&#xff08;Selection Sort&#xff09;是一种简单直观的排序算法。它的基本思想是&#xff1a;每次从待排序的数组中选择最小&#xff08;或最大&#xff09;的元素&#xff0c;将其放在已排序部分的末尾&#xff0c;直到所有元素都排序完毕。…

资源分享—2021版乡级制图规范符号库

汇总整理超图平台软件相关的各类资源&#xff08;包括但不限于符号库、地图模板、地理处理模型等&#xff09;&#xff0c;助力项目的高效制图、提高数据生产效率等业务。 本次分享新版国土空间规划【2021版乡级制图规范符号库】&#xff0c;提供SuperMap格式符号库下载。 符…

简单了解CPU的工作原理

目录 一、基本结构以及对应功能 &#xff08;1&#xff09;基本结构 &#xff08;2&#xff09;几个重要寄存器的详细介绍 操作码 (Opcode) 操作数 (Operands) 指令表 (Instruction Table) 第一个&#xff1a;程序计数器 (PC) 第二个&#xff1a;指令寄存器 (IR&#x…

头歌资源库(3)爬楼梯问题

一、 问题描述 二、算法思想 假设要爬上n阶楼梯&#xff0c;我们可以将问题分解为子问题&#xff1a;爬到第n-1阶楼梯的方法数加上爬到第n-2阶楼梯的方法数加上爬到第n-3阶楼梯的方法数。 设f(n)表示爬到第n阶楼梯的方法数&#xff0c;则有递推关系&#xff1a;f(n) f(n-1…

有声读物管理平台Booksonic-Air

老苏最近在听评书&#xff0c;所以想找个软件来管理和收听&#xff0c;找了一圈&#xff0c;感觉 Booksonic-Air 可能能满足老苏的需求。 什么是 Booksonic-Air &#xff1f; Booksonic-Air 是一个用于流式传输有声读物的服务器&#xff0c;是原始 Booksonic 服务器的后继者。…

windows上运行arm32架构的安卓模拟器

说明 主要功能&#xff1a;在win10上研究和学习32位arm汇编指令的执行 环境如下 主机环境: windows10 目标模拟器环境:armeabi-v7a调试环境搭建 1、下载android studio [下载地址](https://developer.android.com/studio?hlzh-cn) ![在这里插入图片描述](https://img-blog…

RedHat9 | Mariadb数据库的配置与管理

一、实验环境 1、Mariadb数据库介绍 MariaDB数据库管理系统是一个开源的关系型数据库管理系统&#xff0c;与MySQL高度兼容&#xff0c;并提供了更多的功能和性能优化。 起源和背景 MariaDB是MySQL的一个分支&#xff0c;主要由开源社区维护。由MySQL的创始人Michael Widen…

【面试干货】Java集合类详解:List、Set、Queue、Map、Stack的特点与用法

【面试干货】Java集合类详解&#xff1a;List、Set、Queue、Map、Stack的特点与用法 1、Map1.1 特点1.2 用法1.3 常见的实现类 2、Set2.1 特点2.2 用法2.3 常见的实现类 3、List3.1 特点3.2 用法3.3 常见的实现类 4、Queue4.1 特点4.2 用法4.3 常见的实现类 5、Stack5.1 特点5.…