【算法】核心排序算法之堆排序原理及实战

简介: 【算法】核心排序算法之堆排序原理及实战

1.什么是堆排序

  • 指利用堆这种数据结构所设计的一种排序算法将二叉堆的数据进行排序,构建一个有序的序列
  • 排序过程中,只需要个【别临时存储】空间,所以堆排序是原地排序算法,空间复杂度为O(1)
  • 本身大顶堆和小顶堆里面的元素是无序的,只是有一定的规则在里面
  • 大顶堆,每个父节点的值都大于或等于其子节点的值,即根节点的值最大
  • 小顶堆,每个父节点的值都小于或等于其子节点的值,即根节点的值最小

efdbafe5708a47b98818bcbeb92b9212.png

  • 过程分为建堆和排序两大步骤
  • 【建堆】过程的时间复杂度为O(n),排序过程的时间复杂度为O(nlogn),所以 堆排序整体的时间复杂度为O(nlogn)
  • 【堆排序】不是稳定的算法,在排序的过程中,将堆最后一个节点跟堆顶节点互换,可能改变值相同数据的原始相对顺序
  • 流程
  • 把无序数组构建成二叉堆,建堆结束后,整个序列的最大值就是堆顶的根节点
  • 将其与末尾元素进行交换(删除操作), 堆顶a[1]与最后一个元素a[n]交换,最大元素放到下标为n的位置, 末尾就为最大值
  • 然后将剩余n-1个元素重新构造成一个堆(堆化操作),这样会得到n个元素的次小值
  • 反复执行上述步骤,得到一个有序的数组

2.编码实现

  • 无序堆构建成二叉堆
  • 利用二叉堆特性:数组索引一半后的都是叶子节点,不需要做下沉比较;一半前都是非叶子节点,才需要做下沉比较

cf1f89ec101e45e195a668d0505abf0e.png

/**
 * 堆排序
 */
public class HeapSort {
    public static void sort(int[] arr){
        //1.构建堆,数组下标0不存储数据
        int[] heap = new int[arr.length+1];
        //2.根据待排序数组,构建一个无序堆
        System.arraycopy(arr,0,heap,1,arr.length);
        //3.对堆中的元素做下沉操作,从长度一半开始,一半前都是非叶子节点,才需要做
        //二叉堆特性:数组索引一半后的都是叶子节点,不需要做下沉,一半前都是非叶子节点,才需要做
        for (int i = (heap.length)/2; i > 0; i--) {
            down(heap,i,heap.length - i);
        }
        //4.堆排序,把堆顶元素和数组最后一个索引元素交换;然后再堆化,然后堆顶又是最大元素,再和数组倒数第二索引处交换;持续进行直到最后
        //类似删除操作,只需要下沉操作重新堆化即可
        //记录未排序的元素中最大的索引
        int maxUnSortIndex = heap.length - 1;
        //通过循环,交换堆顶元素和最大未排序元素的下标
        while (maxUnSortIndex != 1) {
            //交换元素
            swap(heap, 1, maxUnSortIndex);
            //排序后最大元素所在的索引,不要参与堆的下沉,所以 递减1
            maxUnSortIndex--;
            //继续对堆顶处的元素进行下沉调整
            down(heap, 1, maxUnSortIndex);
        }
        //把heap中的数据复制到原数组source中
        System.arraycopy(heap, 1, arr, 0, arr.length);
    }
    /**
     * 使用下沉操作,堆顶和最后一个元素交换后,重新堆化
     * 不断比较 节点 arr[k]和对应 左节点arr[2*k] 和 右节点arr[2*k+1]的大小,如果当前结点小,则需要交换位置
     * 直到找到 最后一个索引节点比较完成  则结束
     * <p>
     * 数组中下标为 k 的节点
     * 左子节点下标为 2*k 的节点
     * 右子节点就是下标 为 2*k+1 的节点
     * 父节点就是下标为 k/2 取整的节点
     * @param heap
     * @param i
     * @param i1
     */
    private static void down(int[] heap, int k, int range) {
        // 最后一个节点的下标是range,即元素总个数
        while (2 * k <= range) {
            //记录当前节点的左右子节点,较大的节点
            int maxIndex;
            if (2 * k + 1 <= range) {
                if (rightBig(heap, 2 * k, 2 * k + 1)) {
                    maxIndex = 2 * k + 1;
                } else {
                    maxIndex = 2 * k;
                }
            } else {
                maxIndex = 2 * k;
            }
            //比较当前节点和较大接的值,如果当前节点大则结束
            if (heap[k] > heap[maxIndex]) {
                break;
            } else {
                //否则往下一层比较,当前节点的k变为子节点中较大的值
                swap(heap, k, maxIndex);
                k = maxIndex;
            }
        }
    }
    /**
     * 比较大小,item[left] 元素是否小于 item[right]的元素
     */
    private static boolean rightBig(int[] heap, int left, int right) {
        return heap[left] < heap[right];
    }
    /**
     * 交互堆中两个元素的位置
     */
    private static void swap(int[] heap, int i, int j) {
        int temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }
    public static void main(String[] args) {
        //待排序数组
        int[] arr = {923,23,12,4,9932,11,34,49,123,222,880};
        System.out.println("排序前:"+Arrays.toString(arr));
        //堆排序
        HeapSort.sort(arr);
        //输出排序后数组中的元素
        System.out.println("堆排序:"+ Arrays.toString(arr));
    }
}

9496ccd2362f41679dc01e807a52ebec.png

目录
打赏
0
0
0
0
61
分享
相关文章
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
zk基础—1.一致性原理和算法
本文详细介绍了分布式系统的特点、理论及一致性算法。首先分析了分布式系统的五大特点:分布性、对等性、并发性、缺乏全局时钟和故障随时发生。接着探讨了分布式系统理论,包括CAP理论(一致性、可用性、分区容错性)和BASE理论(基本可用、软状态、最终一致性)。文中还深入讲解了两阶段提交(2PC)与三阶段提交(3PC)协议,以及Paxos算法的推导过程和核心思想,强调了其在ZooKeeper中的应用。最后简述了ZAB算法,指出其通过改编的两阶段提交协议确保节点间数据一致性,并在Leader故障时快速恢复服务。这些内容为理解分布式系统的设计与实现提供了全面的基础。
DeepSeek加持的通义灵码2.0 AI程序员实战案例:助力嵌入式开发中的算法生成革新
本文介绍了通义灵码2.0 AI程序员在嵌入式开发中的实战应用。通过安装VS Code插件并登录阿里云账号,用户可切换至DeepSeek V3模型,利用其强大的代码生成能力。实战案例中,AI程序员根据自然语言描述快速生成了C语言的base64编解码算法,包括源代码、头文件、测试代码和CMake编译脚本。即使在编译错误和需求迭代的情况下,AI程序员也能迅速分析问题并修复代码,最终成功实现功能。作者认为,通义灵码2.0显著提升了开发效率,打破了编程语言限制,是AI编程从辅助工具向工程级协同开发转变的重要标志,值得开发者广泛使用。
8339 71
DeepSeek加持的通义灵码2.0 AI程序员实战案例:助力嵌入式开发中的算法生成革新
分布式锁—1.原理算法和使用建议
本文主要探讨了Redis分布式锁的八大问题,包括非原子操作、忘记释放锁、释放其他线程的锁、加锁失败处理、锁重入问题、锁竞争问题、锁超时失效及主从复制问题,并提供了相应的优化措施。接着分析了Redis的RedLock算法,讨论其优缺点以及分布式专家Martin对其的质疑。此外,文章对比了基于Redis和Zookeeper(zk)的分布式锁实现原理,包括获取与释放锁的具体流程。最后总结了两种分布式锁的适用场景及使用建议,指出Redis分布式锁虽有性能优势但模型不够健壮,而zk分布式锁更稳定但部署成本较高。实际应用中需根据业务需求权衡选择。
短视频到底如何推荐的?深度剖析视频算法推送原理详细且专业的解读-优雅草卓伊凡-【01】短视频算法推荐之数据收集
短视频到底如何推荐的?深度剖析视频算法推送原理详细且专业的解读-优雅草卓伊凡-【01】短视频算法推荐之数据收集
279 12
短视频到底如何推荐的?深度剖析视频算法推送原理详细且专业的解读-优雅草卓伊凡-【01】短视频算法推荐之数据收集
JVM实战—3.JVM垃圾回收的算法和全流程
本文详细介绍了JVM内存管理与垃圾回收机制,涵盖以下内容:对象何时被垃圾回收、垃圾回收算法及其优劣、新生代和老年代的垃圾回收算法、Stop the World问题分析、核心流程梳理。
JVM实战—3.JVM垃圾回收的算法和全流程
算法系列之排序算法-堆排序
堆排序(Heap Sort)是一种基于堆数据结构的比较排序算法。它的时间复杂度为 $O(nlogn)$,并且是一种原地排序算法(即不需要额外的存储空间)。堆排序的核心思想是利用堆的性质来维护一个最大堆或最小堆,然后逐步将堆顶元素(最大值或最小值)取出,放到数组的末尾,最终得到一个有序的数组。
109 8
算法系列之排序算法-堆排序
JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码)
Array.sort() 是一个功能强大的方法,通过自定义的比较函数,可以处理各种复杂的排序逻辑。无论是简单的数字排序,还是多字段、嵌套对象、分组排序等高级应用,Array.sort() 都能胜任。同时,通过性能优化技巧(如映射排序)和结合其他数组方法(如 reduce),Array.sort() 可以用来实现高效的数据处理逻辑。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
5月前
|
【📕分布式锁通关指南 04】redis分布式锁的细节问题以及RedLock算法原理
本文深入探讨了基于Redis实现分布式锁时遇到的细节问题及解决方案。首先,针对锁续期问题,提出了通过独立服务、获取锁进程自己续期和异步线程三种方式,并详细介绍了如何利用Lua脚本和守护线程实现自动续期。接着,解决了锁阻塞问题,引入了带超时时间的`tryLock`机制,确保在高并发场景下不会无限等待锁。最后,作为知识扩展,讲解了RedLock算法原理及其在实际业务中的局限性。文章强调,在并发量不高的场景中手写分布式锁可行,但推荐使用更成熟的Redisson框架来实现分布式锁,以保证系统的稳定性和可靠性。
204 0
【📕分布式锁通关指南 04】redis分布式锁的细节问题以及RedLock算法原理
基于PSO粒子群优化的BiLSTM双向长短期记忆网络序列预测算法matlab仿真,对比BiLSTM和LSTM
本项目基于MATLAB2022a/2024b开发,结合粒子群优化(PSO)算法与双向长短期记忆网络(BiLSTM),用于优化序列预测任务中的模型参数。核心代码包含详细中文注释及操作视频,涵盖遗传算法优化过程、BiLSTM网络构建、训练及预测分析。通过PSO优化BiLSTM的超参数(如学习率、隐藏层神经元数等),显著提升模型捕捉长期依赖关系和上下文信息的能力,适用于气象、交通流量等场景。附有运行效果图预览,展示适应度值、RMSE变化及预测结果对比,验证方法有效性。

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问