堆排序实现

简介: 堆排序实现

公众号merlinsea


  • 堆的介绍
  • 堆是一种数据结构,其底层实现是一个完全二叉树,这个完全二叉树满足:任何一个非叶子节点的值都不大于(或者不小于)其左右孩子节点的值。若保证父节点的值大于等于孩子节点的值则称之为大根堆,若保证父节点的值小于等于其孩子节点的值则称之为小根堆

640.png

  • 堆排序的介绍
  • 根据堆堆定义可以知道,堆这棵完全二叉树的根节点是整棵树中的最大值(或者最小值),因此可以将根节点和最后一个节点交换位置,这样我们可以知道有序序列就增多一位,无序序列就减少一位,然后将无序序列重新调整为一个堆,不断重复这个过程,我们就得到了堆排序。
  • 堆排序的本质依旧是选择类排序,但和简单选择排序相比,我们每次选择最值的时间复杂度是O(logn)
  • 堆排序(从小到大排序为例)的流程如下:
  • 将输入的初始序列建立为一个大根堆
  • 将堆顶元素和最后一个元素交换位置
  • 将无序序列重新调整为一个堆
  • 重复第2步骤和第3步骤,直到整个序列有序。


640.png


public class Main {
    public static void main(String[] args) {
        int[] array = new int[]{7,29,32,58,11,45,35,23,45,49};
        System.out.println("元素序列");
        for(int k : array){
            System.out.printf("%d \t",k);
        }
        System.out.println();
        creadMaxHeap(array);
        System.out.println("初始化为大根堆");
        for(int k : array){
            System.out.printf("%d \t",k);
        }
        System.out.println();
        heapSort(array);
        System.out.println("堆排序后");
        for(int k : array){
            System.out.printf("%d \t",k);
        }
        System.out.println();
    }
    //堆排序
    public static void heapSort(int[] arr){
        //无序序列的最后的位置
        int lastIdx = arr.length - 1;
        while(lastIdx>0){
            // 交换
            int temp = arr[0];
            arr[0] = arr[lastIdx];
            arr[lastIdx] = temp;
            lastIdx--;
            //调整堆
            int lastPar = (lastIdx+1)/2-1;
            int cur = 0;
            while(cur<=lastPar){
                //说明cur 有孩子节点
                int maxChild = cur*2+1;
                // 没次调整一个,无序序列就少一个,那么lastIdx就减少1
                if(maxChild+1<=lastIdx && arr[maxChild]<arr[maxChild+1]){
                    maxChild = maxChild + 1;
                }
                if(arr[maxChild]>arr[cur]) {
                    //向下调整
                    temp = arr[cur];
                    arr[cur] = arr[maxChild];
                    arr[maxChild] = temp;
                    cur = maxChild;
                }else{
                    break;
                }
            }
        }
    }
    //建立大根堆
    public static void creadMaxHeap(int[] arr){
        int lastPar = arr.length /2 - 1;
        int cur = lastPar;
        while(cur>=0){
            int par = cur;
            while(par<=lastPar) {
                // 假设孩子节点中最大值是左孩子
                int maxChild = par * 2 + 1;
                if (maxChild + 1 < arr.length && arr[maxChild + 1] > arr[maxChild]) {
                    //若有右孩子并且右孩子是孩子节点中更大的那个,移动maxChild
                    maxChild = maxChild + 1;
                }
                if (arr[maxChild] > arr[par]) {
                    //需要交换位置
                    int temp = arr[maxChild];
                    arr[maxChild] = arr[par];
                    arr[par] = temp;
                    //继续向下调整
                    par = maxChild;
                } else {
                    break;
                }
            }
            cur--;
        }
    }
}


  • 堆排序的性能分析
  • 算法时间复杂度:堆排序的时间主要耗费在将无序序列部分调整为堆的过程,每次调整需要比较的最大次数是完全二叉树的高度,因此堆排序的时间复杂度的上限是O(nlogn)
  • 算法空间复杂度:由于堆排序是基于原始输入的数组进行排序的,因此空间复杂度是O(1)
  • 算法稳定性分析:堆排序是不稳定排序。


算法训练营永久刷题班元旦优惠价,超低价格永久刷题。加入我们可以一起备战明年的春招笔试,快来参加吧~


算法训练营元旦福利

奔跑的小梁,公众号:梁霖编程工具库leetcode刷题直播教学,手把手带你刷题,元旦价格优惠通知,超低价格永久刷题


相关文章
|
机器学习/深度学习 自然语言处理 算法
跨模态学习能力再升级,EasyNLP电商文图检索效果刷新SOTA
本⽂简要介绍我们在电商下对CLIP模型的优化,以及上述模型在公开数据集上的评测结果。最后,我们介绍如何在EasyNLP框架中调用上述电商CLIP模型。
|
存储 SQL 算法
Mysql进阶索引篇02——InnoDB存储引擎的数据存储结构(一)
前面我们已经剖析了mysql中InnoDB与MyISAM索引的数据结构,了解了B+树的设计思想、原理,并且介绍了B+树与Hash结构、平衡二叉树、AVL树、B树等的区别和实际应用场景。 页和页之间并不一定在物理上相连,只是在逻辑上使用双向链表关联。指针、记录究竟是如何存储的呢?其实这就需要联系我们之前提到的行格式了。数据查找在页目录中二分法快速定位到槽,上面的过程都与页的内部结构相关,本文将详细的阐述。
Mysql进阶索引篇02——InnoDB存储引擎的数据存储结构(一)
|
10月前
|
安全 Unix 虚拟化
Windows 7 & Windows Server 2008 R2 简体中文版下载 (2025 年 2 月更新)
Windows 7 & Windows Server 2008 R2 简体中文版下载 (2025 年 2 月更新)
382 11
Windows 7 & Windows Server 2008 R2 简体中文版下载 (2025 年 2 月更新)
|
安全 Java Spring
Spring Security系列教程19--会话管理之处理会话过期
前言 在上一章节中,一一哥 给各位讲解了HTTP协议、会话、URL重新、会话固定攻击等概念,并且实现了对会话固定攻击的防御拦截。 在Spring Security中,其实除了可以对会话固定攻击进行拦截之外,还可以对会话过期进行处理,也就是会话可能会过期,过期了该怎么处理。接下来请各位跟着 壹哥 继续学习,看看会话过期时到底怎么处理的吧。 一. 会话过期 1. 会话过期概念 在处理会话过期之前,我们首先得知道啥是会话过期。 所谓的会话过期,是指当用户登录网站后,较长一段时间没有与服务器进行交互,将会导致服务器上的用户会话数据(即session)被销毁。此时,当用户再次操作网页时,如果服务器进
979 0
|
存储 监控 API
史上最全最完整,最详细,软件保护技术-程序脱壳篇-逆向工程学习记录(二)
本文详细介绍了软件保护技术中的程序脱壳过程,包括IAT(导入地址表)的重建、OD(OllyDbg)跟踪输入表、HOOK-API技术以及FSG、UPX和WinUpacx等常见压缩壳的加脱壳方法。文章通过具体实例和详细步骤,帮助读者理解并掌握逆向工程的基本技巧。[原文链接](https://developer.aliyun.com/article/1618653)
424 0
|
Web App开发 JavaScript 前端开发
JavaScript——定时器为什么是不精确的
JavaScript——定时器为什么是不精确的
210 0
|
网络安全 开发工具 git
|
XML Java Android开发
Android Studio App开发实战项目之计时器(附源码 简单易懂,适合新手学习)
vAndroid Studio App开发实战项目之计时器(附源码 简单易懂,适合新手学习)
635 0
|
前端开发 JavaScript C++
深入探索WebAssembly在前端性能优化中的应用
随着Web应用的功能越来越复杂,传统的JavaScript解释执行模式已经逐渐成为性能瓶颈。本文将介绍WebAssembly(以下简称Wasm)的基本概念、优势以及如何在现代Web开发中利用Wasm提升前端性能。我们将通过实际案例分析Wasm在处理高性能计算任务时相比JavaScript的优势,并探讨如何将Wasm集成到现有的前端项目中,以实现无缝的性能优化。本文旨在为前端开发者提供一个全面的Wasm应用指南,帮助他们充分利用这一新技术,提升Web应用的响应速度和用户体验。
474 0