堆排序算法

【树与二叉树】堆的时间复杂度详解以及堆的应用—堆排序、TOP - K问题 今天我们认识并学习了堆的时间复杂度,并且通过分析对向下调整算法和向上调整算法也有了更深入的了解。还对堆的应用——堆排序、TOP - K问题进行了分析。下一篇博客我们将对二叉树链式结构进行分析及实现。希望我的文章和讲解能对大家的学习提供一些帮助。 阅读详情

堆排序

堆排序时间复杂度为Ο(nlgn),并且具有空间原址性。同时堆排序还引入了另一种设计技巧:使用堆的数据结构进行信息管理

堆

二叉堆可以近似看成一颗完全二叉树,除了叶子节点,该树是被完全填充,并且是从左到右填充,表示堆的数组包含两个属性,A.length表示数组元素个数;A.heap-size表示有多少个堆元素存储在该数组中。0 ≤ A.heap-size ≤ A.length,根节点为A[1],父节点为i/2, 左孩子为2i,右孩子为2i + 1.
在这里插入图片描述

通过将i的值左移一位,LEFT过程可以在一条指令内计算2i,RIGHT过程可以通过将i左移1位并在低位加1,得到2i + 1.PARENT可以将i右移一位得到i/2

二叉堆可以分为两种形式

  • 最大堆

  • 最小堆

最大堆

最大堆是指除根以外的所有节点i都要满足:A[PARENT(i)] ≥ A[i]。某个结点的值至多与其父结点一样,堆中的最大元素存放在根结点中,在任意子数中,该子树中所有节点的值都不大于该子树根节点值

最小堆

最小堆指除根结点外的所有节点i都满足:A[PARENT(i)] ≤ A[i].最小堆的最小元素存放在根节点中,最小堆通常用于构造优先队列

维护堆的性质

MAX-HEAPIFY是用于维护最大堆性质的重要过程。其时间复杂度为Ο(lgn)。其接收一个数组A和下标i,假定根节点为LEFT(i)和RIGHT(i)的二叉树都是最大堆,A[i]可能小于其孩子,我们通过让A[i]的值在最大堆中逐级下降,从而使得以下标i为根节点的子树重新遵循最大堆性质

MAX-HEAPIFY(A, i)
1   l = LEFT(i)
2   r = RIGHT(i)
3   if l ≤ A.heap-size and A[l] > A[i]
4       largest = l
5   else largest = i
6   if r ≤ A.heap-size and A[r] > A[largest]
7       largest = r
8   if largest ≠ i
9       exchange A[i] with A[largest]
10      MAX-HEAPIFY(A, largest)

算法首先从A[i]、A[LEFT(i)]、A[RIGHT(i)]中选出最大值,并将下标存储在largest中。如果A[i]是最大值,则该子树为最大堆。若A[i]不是最大值,则最大值为其某个孩子,交换A[i]、A[largest],使i及其孩子满足最大堆。在交换后下标为largest节点的值为原来的A[i],以该节点为根的子树有可能也违反了最大堆性质,需要递归调用MAX-HEAPIFY

MAX-HEAPIFY时间代价包括:调整A[i]、A[LEFT(i)]、A[RIGHT(i)]关系的时间代价,加上一颗以i的一个孩子为根节点的子树上运行MAX-HEAPIFY的时间代价。每个孩子子树的大小至多为2n/3。MAX-HEAPIFY运行时间为

    T(n) ≤ T(2n/3) + θ(1)

因此时间复杂度为T(n) = O(lgn)

建堆

可以采用自底向上的方法利用过程MAX-HEAPIFY把一个大小为n=A.length的数组A[1…n]转换为最大堆。子数组A(└n/2┘ + 1…n)中的元素都是数的叶子节点。过程BUILD-MAX-HEAP对树中其它节点都调用一次MAX-HEAPIFY

BUILD-MAX-HEAP(A)
1   A.heap-size = A.length
2   for i = └A.length/2┘ downto 1
3       MAX-HEAPIFY(A, i)

堆排序算法

堆排序算法利用BUILD_MAX_HEAP将输入数组A[1…n]建成最大堆,n = A.length.因为数组最大元素总在节点A[1], 通过把它与A[n]互换,可以让该元素放到正确位置,即按从小到大的顺序组织数组。如果从堆中去掉节点n,剩余的结点中,原来根的孩子节点仍然是最大堆,而新的根节点可能违背最大堆性质。为维护最大堆的性质,调用MAX-HEAPIFY(A, 1),从而在A[1…n-1]上构造一个新的最大堆。堆排序算法会不断重复这一过程,直到堆的大小从n-1降到2

HEAPSORT(A)
1   BUILD-MAX-HEAP(A)
2   for i = A.length downto 2
3       exchange A[1] with A[i]
4       A.heap-size = A.heap-size - 1
5       MAX-HEAPIFY(A, 1)

第一行建立初始最大堆,第2~5行循环第一次迭代开始前堆大堆的情况和每一次迭代之后最大堆情况。HEAPSORT过程时间复杂度为O(nlgn)。每次BUILD-MAX-HEAP的时间复杂度为O(n), n-1次调用MAX-HEAPIFY,每次时间为O(lgn)

Java 实现

package com.aim.algorithm.sort.impl;

import com.aim.algorithm.sort.Sort;

public class HeapSort implements Sort {
    @Override
    public int[] sort(int[] input) {
        return heapSort(input);
    }

    private void maxHeapify(int[] input, int heapSize, int i) {
        int l = 2 * i + 1;
        int r = 2 * i + 2;
        int largest = i;
        if (l < heapSize && input[l] > input[i]) {
            largest = l;
        }
        if (r < heapSize && input[r] > input[largest]) {
            largest = r;
        }
        if (largest != i) {
            input[i] = input[i] ^ input[largest];
            input[largest] = input[i] ^ input[largest];
            input[i] = input[i] ^ input[largest];
            maxHeapify(input, heapSize, largest);
        }
    }


    private void buildMaxHeap(int[] input) {
        for (int i = input.length / 2 - 1; i >= 0; i--) {
            maxHeapify(input, input.length, i);
        }
    }

    private int[] heapSort(int[] input) {
        int heapSize = input.length;
        buildMaxHeap(input);
        for (int i = input.length - 1; i >= 1; i--) {
            input[0] = input[0] ^ input[i];
            input[i] = input[0] ^ input[i];
            input[0] = input[0] ^ input[i];
            heapSize--;
            maxHeapify(input, heapSize, 0);
        }
        return input;
    }
}

// 测试方法
public static void heapSort() throws IOException {
    Scanner scan = new Scanner(System.in);
    System.out.println("请输入要排序数组");
    String arrayStr = scan.nextLine();
    while (Strings.isBlank(arrayStr)) {
        System.out.println("请输入要排序数组");
        arrayStr = scan.nextLine();
    }
    String[] arrays = arrayStr.split(" ");
    int[] input = Arrays.stream(arrays).mapToInt(array -> Integer.valueOf(array)).toArray();

    int[] result = heapSort.sort(input);
    Arrays.stream(result).forEach(rsl -> System.out.println(rsl));
}
【算法】堆排序 基础排序算法之一:堆排序。 阅读详情

相关推荐

实现堆排序算法

堆排序是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。 /** *    实验题目: *        实现堆排序算法 *    实验目的: *      ...

xiezhi123456的博客 2552

堆排序时间复杂度_堆排序算法

堆排序是指利用堆积树这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆是一个优先级队列,对于大顶堆而言,堆顶元素的权值最大。将待排序的数组建堆,然后不断地删除堆顶元素,就实现了排序。堆排序基本思想将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这...

weixin_39844942的博客 2万+

堆排序算法的实现

1、什么是堆 “(二叉)堆是一个数组,它可以被看成一个近似的完全二叉树。树上的每一个节点对应数组中的一个元素。除了最底层外,该树是完全充满的,而且是从左到右填充”。这是算法导论里对堆的定义,说得很清晰明了,当然最好还是得上个图,所以这里就顺便也从算法导论里盗个图了。。。。 二叉堆可以分为两种形式,最大堆和最小堆。在这两种堆中,节点的值都要满足堆的性质,同时在最大堆中,除了根以外的所有节...

sh805499910的博客 1964

排序算法-堆排序和时间复杂度

堆排序分为两个部分:堆调整+堆排序 堆排序的思路:将一个已知的序列先调整到大堆的形式,然后再将堆顶元素和堆最后的元素进行调换(这样最大的元素就在最后面了),减去最后一个元素将剩余的元素进行堆调整,重复上面的步骤就会生成从小到大的序列。 这里牵扯到两个概念,一个是调整大堆,另一个是对堆顶元素和最后一个元素调换的理解 首先,先来看调整大堆 调整大堆的核心思路是:找到parent,rchild,lchi...

阿巴卡的博客 1万+

【python算法系列四】堆排序算法

堆排序,就像它的名字一样,利用了堆的特性来进行排序。实现堆排序的思路是,把数组构建成一棵二叉树,并随着每次堆的变化更新堆顶的最大/最小值。堆排序的时间复杂度在所有情况下都是 O(nlgn),它也是一个不稳定的算法。在开始编写堆排序的程序之前,我们首先要了解“堆”的概念。 堆是一种数据结构,它是一种特殊的完全二叉树:如果这个堆是一个大顶堆(最大的元素在堆顶),那么每个节点上的元素都应该比它的子节点上的元素要大,最大的元素在根节点上;反之,如果是小顶堆,那么每个节点上的元素都应该比它的子节点小,最小的元素在根节

m0_70372647的博客 2403

算法设计与分析——堆排序

算法设计与分析、堆排序、JavaScript算法、C语言算法、排序算法、高效算法

A_FLY_User的博客 1565

堆排序时间复杂度

注:本文转载于两篇博文,感谢博主 转载于: https://blog.youkuaiyun.com/yuzhihui_no1/article/details/44258297 https://blog.youkuaiyun.com/qq_34228570/article/details/80024306 堆排序是由1991年的计算机先驱奖获得者、斯坦福大学计算机科学系教授罗伯特.弗洛伊德(Robert W.Fl...

NDHuaErFeiFei的博客 9587

【电子元件篇】电力电子中的变压器原理、作用、选型与测量指南-超简单解读

变压器虽小,却是电力电子的 “关键纽带”——从识别符号型号,到理解 “传交流隔直流” 的特点,再到按用途选参数、用万用表检测,只要抓住 “场景对应核心” 的逻辑,就能轻松掌握它的用法。

2301_81299416的博客 3031

堆排序及其时间复杂度(C语言)

啊?不用建堆那还怎么堆排序啊?是这样的,堆排序,未必要做一个堆出来,堆的结构本质是数组,那么我们针对数组来巧妙操作就可以完成,省去大量时间来写定义堆相关的函数。

zxy13149285776的博客 2891

避坑指南:Zabbix poller进程100%占用的5种常见原因及解决方案

本文深入剖析了Zabbix poller进程占用率高达100%的五大常见原因,包括监控项与进程数不匹配、不可达主机资源浪费、数据库性能瓶颈、监控项配置不合理以及版本缺陷。文章提供了从系统化诊断到针对性解决方案的完整指南,并重点介绍了如何通过优化zabbix_server.conf中的StartPollers等关键参数进行有效调优,帮助运维人员从根本上解决这一经典性能问题。

7z8x2c4v6b9的博客 253

保姆级教程:用xmir-patcher一键解锁Redmi AX3000路由器的SSH(附视频演示)

本文提供Redmi AX3000路由器SSH解锁的保姆级教程,详细介绍了使用xmir-patcher工具一键解锁SSH的步骤,包括环境搭建、工具获取、图形化操作详解及常见问题排查。解锁后,用户可通过SSH连接实现刷机、插件安装、网络优化等高级功能,提升路由器性能。

weixin_29216049的博客 738

必学排序算法——堆排序

堆排序算法是必须掌握的一种基础算法,在一些比较出名的竞赛acm、蓝桥杯,并且在一些公司面试题中都可能会出现,而且作为简单题我们必须要拿下,所以我们要引起重视,下面让我们来深入了解堆排序算法。堆排序(Heap Sort)是一种基于堆数据结构的比较排序算法。堆是一个近似完全二叉树的结构,分为最大堆和最小堆。在最大堆中,父节点的值总是大于或等于其子节点的值;而在最小堆中,父节点的值总是小于或等于其子节点的值。堆排序通常使用最大堆来升序排序数组,使用最小堆则可以降序排序数组。

ycs66的博客 3998

java结合Ai

Spring AI 是 AI 工程的应用框架。其目标是将Spring生态系统的设计原则(如可移植性和模块化设计)应用于AI领域,并促进使用POJO作为应用程序的构建块到AI领域。特征跨 AI 提供商的可移植 API 支持,适用于聊天、文本到图像和嵌入模型。支持同步 API 和流 API 选项。还支持下拉以访问特定于模型的功能。聊天模型亚马逊基岩人类学Cohere的命令AI21 Labs的侏罗纪-2Meta 的 LLama亚马逊的泰坦人类学克劳德Azure 开放式 AI。

qq_67832732的博客 2850

堆排序与堆排序算法

堆排序概念 堆排序,将数组当作二叉树的形式进行排序,根据排序的不同形式分为大堆顶与小堆顶 并且是一颗完全二叉树(不是满二叉树) 完全二叉树 满二叉树 堆排序后的数组性质 其排序的二叉树后满足如下条件(以大堆顶进行举例) 每个节点(包括根节点)的子节点及其所有子节点均`小于`该节点(即在他下面的全部都比他小,不管是否是直接子节点) 由于是数组来表示树的结构,所以满足如下性质 //此处将数组下标为0的位置不使用 //如果非要使用下标0的单元,则以下的性质与算法需要根据实际使用进行减去相差位数 根节点为数组第

weixin_44019654的博客 1310

matlab相机标定_实战 | 相机标定

点击“计算机视觉life”关注,置顶更快接收消息!本文阅读时间约5分钟什么是相机标定?我们为什么需要相机标定?相机标定就是确定相机内参和外参的过程,其结果精度会直接影响视觉系统后续工作的准确性。坐标系相机标定涉及到了四大坐标系,分别为:像素坐标系图像物理坐标系相机坐标系世界坐标系为了进行相机标定,必须已知世界坐标系中足够多的三维空间点坐标,找到这些空间点在图像中投影点的二维图像坐标,并建...

weixin_39747334的博客 765

LVGL(lv_table)

LVGL中的lv_table是一个轻量级表格控件,用于显示行列式文本数据。它支持设置单元格内容/样式、行列调整、事件响应等基础功能,适用于参数配置、数据展示等场景。通过API可快速创建表格,设置行列数、填充数据,并自定义对齐方式与样式。但需注意默认无滚动条、行数限制等问题。该控件适合简单表格需求,复杂交互需结合自定义事件处理。

m0_49476241的博客 1267

[算法沉淀记录] 排序算法 —— 堆排序

堆排序(Heap Sort)是一种基于比较的排序算法,它利用堆这种数据结构来实现排序。堆是一种特殊的完全二叉树,其中每个节点的值都必须大于或等于(最大堆)或小于或等于(最小堆)其子节点的值。堆是一个近似完全二叉树的数据结构,满足任一非叶子节点的值不小于(或不大于)其左右孩子节点的值。堆通常分为最大堆和最小堆:堆排序算法通过构建一个最大堆或最小堆,然后将堆顶元素(最大或最小值)与堆的最后一个元素交换,再将剩余的元素重新调整为最大堆或最小堆,如此反复,直到整个数组有序。堆排序是一种高效的排序算法、

莫寒技术人生 2226

论文阅读:ICLR 2026 Breaking and Fixing Defenses Against Control-Flow Hijacking in Multi-Agent Systems

该论文首先系统阐述了控制流劫持攻击的核心机理。此类攻击通过操纵多智能体系统的编排机制,诱导系统执行非安全操作,进而实现敏感信息窃取。攻击者将恶意指令伪装成环境错误信息,借助可信代理传递至系统编排器,利用"困惑副手"漏洞绕过传统安全防线。该论文指出,现有防御方案如LlamaFirewall所依赖的对齐检查机制存在根本性局限——安全目标与功能需求之间存在不可调和的内在冲突。该论文的核心贡献体现在攻防两个维度。

CSPhD-winston的博客 495

堆排序算法-JS

一、堆排序算法介绍 堆是一种特殊的树形数据结构,其每个结点都有一个值,通常提到的堆都是指一棵完全二叉树,根结点的值小于(或大于)两个子结点的值,同时,根结点的两棵子树也分别是-个堆。堆排序是一种树形选择排序,在排序过程中,将R[...n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结 点和孩子结之间的内在关系来选择最小的元素。 堆一般分为大顶堆和小顶堆两种不同的类型。对于给定n个记录的序列(r(1), r(2), ... r(n)),当且仅当满足条件(r(i)≥r(2i)&am...

qq_42099097的博客 899

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

堆排序算法思路总结

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

qq_34729246的博客 862

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

堆排序算法过程图解_堆排序算法

堆排序算法过程图解 堆排序算法 (Heap Sort Algorithm) Heap Sort is one of the best sorting methods being in-place and with no quadratic worst-case running time. Heap sort involves building a Heap data structure from...

cunfen6312的博客 1859

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

上一篇: startOffset与resetOffsets
下一篇: 优先队列
炒栗子不加糖
博客等级 码龄10年 68粉丝 123原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值