十大排序之堆排序(详解)

文章目录

  • 🐒个人主页
  • 🏅算法思维框架
    • 📖前言:
  • 🎀堆排序 时间复杂度O(n*logn)
      • 🎇1. 算法步骤思想
      • 🎇2、动画演示
      • 🎇3.代码实现

🐒个人主页

🏅算法思维框架

📖前言:

本篇博客主要以介绍十大排序算法中的堆排序,有详细的图解、动画演示、良好的代码注释,帮助加深对这些算法的理解,进行查漏补缺~

🎀堆排序 时间复杂度O(n*logn)

堆排序(Heapsort) 是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:
大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列; 堆排序的平均时间复杂度为 Ο(nlogn)。

有好多人都说堆排序代码有点复杂但是它的思路其实是最好理解的!他的思路是将大根堆顶的最大值元素放到数组没有排序区间的末尾,然后对没有排序的区间重新变成大根堆,直到没有排序的区间中只剩一个元素,就排好序了。
难的无非是不会将一个数组变成堆heapify,也不会取出堆顶元素后(删除操作(下沉操作)),再将其变成堆

🎇1. 算法步骤思想

  1. 创建一个堆 H[0……n-1] ;【heapify()操作----->时间复杂度O(n)】
  2. 把堆首(最大值)和堆尾互换;【交换数组中的堆顶与数组未排序区间的末尾元素】
  3. 调用swim()方法----->时间复杂度O(logn),使除过堆尾元素的树满足最大堆的性质;【对没有排序的区间进行下沉操作,重新生成堆】
  4. 重复步骤 2,直到堆中只有一个元素。

🎇2、动画演示

在这里插入图片描述
在这里插入图片描述

🎇3.代码实现

public int[] sort(int[] nums) {
        if(nums==null||nums.length<2){
            return nums;
        }
        //思路:【堆排序】:先将nums[]构建成大根堆heapify()操作,
        // 再将堆顶元素与未排序区间的末尾元素进行交换,对此时的堆顶元素进行【无序区间】的下沉操作,重复上述操作....直至数组有序
        heapify(nums);//【将nums[]数组变成堆】
        //进行排序
        for (int i = nums.length-1; i >0; i--) {
            //交换
            int temp=nums[i];
            nums[i]=nums[0];
            nums[0]=temp;
            //对根节点进下沉操作,让没有排序的区间重新变成堆
            swim(nums,0,i);
        }
        return nums;
    }
    //写两个辅助方法:获取父亲节点下标,获取左孩子节点下标
    private int getParentIndex(int childIndex){
        return (childIndex-1)/2;
    }
    private int getLeftChildIndex(int parentIndex){
        return 2*parentIndex+1;
    }
    private void heapify(int[] nums){//【将nums[]数组变成堆】
        //思路:拿到数组最后一个元素的父亲节点下标,直到根节点,依次进行下沉操作
        int lastParentIndex=getParentIndex(nums.length-1);
        for (int i = lastParentIndex; i >=0 ; i--) {
            swim(nums,i,nums.length);
        }
    }

    /**
     * 下沉操作
     * @param nums 进行下沉操作的数组
     * @param index  需要进行下沉操作的节点
     * @param length 进行下沉操作的区间长度
     */
    private void swim(int[] nums,int index,int length){
        //下沉思路:将目标值rootVal与当前节点index的左右孩子最大优先级进行比较:
        // 1.如果rootVal<孩子优先级,孩子优先级覆盖当前父亲节点index,index索引最大优先级的孩子,重新找孩子进行比较
        // 2.如果rootVal>=孩子优先级,找到了break,将当前节点nums[index]=rootVal
        //3.如果找到头都没有找到,将当前节点nums[index]=rootVal            【情况2、3可合并处理】
        int rootVal=nums[index];//寄存将要下沉节点的值
        int leftIndex=getLeftChildIndex(index);//获取当前节点的左孩子
        int maxChildPiroirtyIndex=leftIndex;//【默认左孩子为孩子的最大优先级,原因堆是一棵完全二叉树...】
        while (leftIndex<length){//左孩子存在
            int rightIndex=leftIndex+1;//右孩子下标
            if(rightIndex<length&&nums[leftIndex]<nums[rightIndex]){//左孩子存在且左孩子优先级<右孩子优先级
                maxChildPiroirtyIndex=rightIndex;
            }
            //进行优先级的比较
            if(rootVal<nums[maxChildPiroirtyIndex]){
                nums[index]=nums[maxChildPiroirtyIndex];//覆盖父节点
                //更新索引指向
                index=maxChildPiroirtyIndex;
                leftIndex=getLeftChildIndex(index);
                maxChildPiroirtyIndex=leftIndex;
            }else {
                break;
            }
        }
        nums[index]=rootVal;//插入目标值
    }

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

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

相关文章

Openwrt 包管理系统介绍

Openwrt 包管理系统介绍 1. OpenWrt简介1.1 主要特点1.2 开源嵌入式操作系统1.2.1 嵌入式系统概念1.2.2 嵌入式系统分类1.2.3 嵌入式系统——安卓1.2.4 嵌入式系统的对比 2 OpenWrt包管理系统2.1 工作原理2.2 OPKG命令2.2.1 命令用法2.2.2 软件包的管理2.2.3 查询信息2.2.4 选项…

设计测试用例的具体方法总结

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️白马沉河共歃誓&#xff0c;怒涛没城亦不悔 ☁️基于需求进行测试用例的设计 基…

vue3 for循环创建的多个e-form 添加校验

v-for 创建 ref <el-form :model"item" :rules"state.rules" :ref"el > getRiskSpreadRef(el, index)" ></el-form>// 定义ref list const riskSpreadRefList ref<HTMLElement[]>([]);// ref存到数组 const getRiskSpread…

初始linux:文件操作

目录 提示&#xff1a;以下指令均在Xshell 7 中进行 linux的理念 一、echo echo "字符串" 二、输出重定向 > > [文件] echo "字符串" > [文件] echo "字符串" > > [文件] 制作大文件 三、< 输入重定向与ca…

【开源】基于JAVA的森林火灾预警系统

项目编号&#xff1a; S 019 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S019&#xff0c;文末获取源码。} 项目编号&#xff1a;S019&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 系统基础模块2.3 烟…

QT已有项目导入工程时注意事项

文章目录 从qt其他版本上开发的工程导入另一qt版本时 从qt其他版本上开发的工程导入另一qt版本时 这里以之前在qt5.12.2上开发的项目为例&#xff0c;现在到在qt6.5.3上运行。 不能直接导入IDE上&#xff0c;否则会报各种莫名奇妙的错误。 首先要把扩展名位.pro.user文件 删掉…

面试题:说说什么是本地缓存、分布式缓存以及多级缓存,它们各自的优缺点?

文章目录 前言一、缓存的概念&#xff08;什么是缓存&#xff09;二、为什么要用缓存&#xff08;为什么要用redis作为缓存&#xff09;三、缓存的分类有哪些1、本地缓存2、分布式缓存3、多级缓存 总结 前言 像MySql等传统的关系型数据库已经不能适用于所有的业务场景&#xf…

kubernetes使用nfs创建pvc部署mysql stateful的方法

kubernetes创建的pod默认都是无状态的&#xff0c;换句话说删除以后不会保留任何数据。 所以对于mysql这种有状态的应用&#xff0c;必须使用持久化存储作为支撑&#xff0c;才能部署成有状态的stateful. 最简单的方法就是使用nfs作为网络存储&#xff0c;因为nfs存储很容易被…

Leetcode—58.最后一个单词的长度【简单】

2023每日刷题&#xff08;四十&#xff09; Leetcode—58.最后一个单词的长度 实现代码 int lengthOfLastWord(char* s) {int len strlen(s);int left 0, right 0;if(len 1) {return 1;}while(right < len) {if(right 1 < len) {if(s[right] && s[righ…

激活函数与非线性化:探索神经网络中的关键元素

随着人工智能领域的迅猛发展&#xff0c;神经网络成为实现各种复杂任务的有力工具。其中&#xff0c;激活函数及其非线性化特性扮演着至关重要的角色。本文将深入探讨激活函数的基本概念、作用原理以及常见的几种激活函数&#xff0c;并介绍它们在神经网络中发挥的重要作用。 …

Odoo:行业领先的免费开源生产制造管理系统

产品生命周期管理 用 Odoo 产品数据管理解决方案加速产品开发 研究、开发和设计新产品或者重新设计现有产品是所有制造企业的活力之源&#xff0c;但很多企业的设计部门和工程部门却完全脱离 ERP 系统。这导致工程师需要耗费大量时间来回答企业中其他部门就产品状态、修改级别…

【小技巧】复制一个模块到你的工程(学习阶段很实用)

问题描述&#xff1a; 当我们学习Springboot时&#xff0c;需要创建大量的模块&#xff0c;而这些模块的许多代码都是重复的&#xff0c;只有模块名等相关的信息不一样&#xff0c;现在就教你如何快速创建一个模块。 应用场景&#xff1a; ①进入项目文件夹&#xff1a; ②复…

Java实现—数据结构 1.初识集合框架

一、什么是集合框架 Java集合框架&#xff0c;又被称为容器&#xff0c;是定义在java.util包下的一组接口interfaces和其实现类classes 其主要表现为将多个元素element置于一个单元中&#xff0c; 集合框架是由若干个类组成的&#xff0c;每个类的背后就是一种数据结构&…

webpack 打包优化

在vue.config.js中配置 下载 uglifyjs-webpack-plugin 包 const { defineConfig } require("vue/cli-service"); var path require("path");module.exports defineConfig({transpileDependencies: true,filenameHashing: false, // 去除Vue打包后.cs…

window获取密码工具

工具getpass.exe 运行输出密码到5.txt 工具gethashes.exe 运行之后输入到6.txt,会得到一个$local 再运行gethashes.exe $local 可以看到加密的账户密码&#xff0c;用工具进行解密就可以得到密码 工具pwdump7 还有其他的mimikatz&#xff0c;msf工具都可以获取。

canvas扩展001:利用fabric绘制图形,可以平移,旋转,放缩

canvas实例应用100 专栏提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。 canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重要的帮助。 文章目录 示例…

frp V0.52.3 搭建

下载 https://github.com/fatedier/frp/releases/ 此版本暂时没有windows的&#xff0c;想在windows使用请下载v0.52.2 简易搭建 frps.toml的配置文件&#xff0c;以下12000、8500需要在云服务器中的防火墙中开放tcp # bindPort为frps和frpc通信的端口&#xff0c;需要在防…

Git控制指令

git status查看当前本地分支的修改状态 git diff 文件路径 查看具体文件的修改内容 git log打印用户信息 git remote -v查看远程地址 git checkout -- *还原被删除的文件 git rm -r --force .删除本地所有文件 git commit -m "Remove all files from repositor…

基于C#实现外排序

一、N 路归并排序 1.1、概序 我们知道算法中有一种叫做分治思想&#xff0c;一个大问题我们可以采取分而治之&#xff0c;各个突破&#xff0c;当子问题解决了&#xff0c;大问题也就 KO 了&#xff0c;还有一点我们知道内排序的归并排序是采用二路归并的&#xff0c;因为分治…

crontab 定时检测 Tomcat 状态脚本实现及注意事项

背景 Jenkins 所在的 Tomcat 总是莫名挂掉&#xff0c;虽然任务配置了 NOKILLME 参数&#xff0c;而且并不是总是发生在编译完成后才挂的。怀疑是机器资源不足导致的&#xff0c;没有依据。最简单的办法是创建一个定时任务&#xff0c;检测 Tomcat 状态&#xff0c;不见了就拉…