当前位置: 首页 > news >正文

数组(完全二叉树)向下建堆法与堆排序O(N*logN)

TIPS

AdjustUp & AdjustDown

  1. 向上调整AdjustUp与向下调整AdjustDown的参数是一个数组(完全二叉树)+需要进行调整操作的数值的下标/一个数组(完全二叉树)+堆元素个数+需要调整操作的数值的下标

  1. 实际上就是对完全二叉树当中的某一点进行调整直至在其局部范围内满足堆的性质。因此对于完全二叉树如果仅仅对若干个值进行AdjustUp/AdjustDown,并不会是这颗完全二叉树真正变成一个堆

  1. 对于AdjustUp与AdjustDown,在没有任何限制与约束的情况之下,如果说你对数组(完全二叉树)中的某一个元素去进行调整的话,你可以这么做,只不过没有任何意义,因为他最终调整调整,直至在某一个局部范围内满足堆的性质。既然没有任何意义,那它的意义到底是什么呢?AdjustUp与AdjustDown的意义就在于建堆

  1. 那如果说想使用这两个函数往建堆这条正确的方向去走,需要注意:


AdjustUp的前提必须是在child前面数据已经是一个堆;AdjustDown的前提必须是在parent左右两个子树必须是两个堆在这些前提之下,如果说你去AdjustUp与AdjustDown,那么是真正在朝着建堆前进。不然,你在怎么弄的话,只是在局部范围内进行兴风作浪,对于整体并不能使它变成一个堆。


HeapPush & HeapPop

  1. HeapPush与HeapPop的本质与灵魂就是AdjustUp/AdjustDown。这两个的参数分别是一个堆结构体指针+一个需要往堆里面插入的值,一个堆结构体指针

  1. 因此这两个函数的话需要在原先的数组(完全二叉树)就是一个堆的情况下才有意义,不然的话,如果说原先的数组并不是一个堆,那么插入一个数的操作与删除第一个元素意义不大。


数组(完全二叉树)建堆(向下建堆法)O(N)

  1. 我们讲过一个建堆方式,就是说是向上调整法建堆,实际上就是不断的插入,如果对于一个数据仅仅进行AdjustUp,只会最终使得局部范围内满足堆的性质,如果说我对数组(完全二叉树)当中的每一个数都进行AdjustUp,那么当我这个操作完了之后,这个数组(完全二叉树)我已经是一个堆了。那有没有其他的方式去建堆呢?

  1. 然后我们再进行向下调整法建堆的时候,显而易见的事实就是,我说你对叶子(就是说没有儿子的节点)进行向下调整,那还有什么意义?没有儿子,他调整的也跟白调一样。

  1. 所以说向下调整法的话,我需要从倒着往前走,这是第一点(这就为了使得AdjustDown朝着建堆的方向走

  1. 并且从倒着往前走之外,我还要从第一个非叶子节点开始进行向下调整。那我该怎么样去找到倒数第一个非叶子节点?我只要把最后一个元素的下标(child)这样((child-1)/2)找到他父亲不就万事大吉了吗?

  1. 为什么要倒着走呢?因为倒着走去向下调整的时候,我就可以确保目前这个节点的左右两个子树都已经是堆,这样子的话,我就确保AdjustDown的能够朝着正确的方向(建堆)前进,而不是一直在局部范围内在兴风作浪。

  1. 然后向下调整法建堆的话,它的效率比向上调整法建堆要高且差距极大。一般建堆的话是不会用向上调整建堆。

  1. 当然,要对数组(完全二叉树)建堆,首先必须得有两个万金油(AdjustUp 与 AdjustDown)

void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
void AdjustUp(int* a, int child)
{assert(a);int parent = (child - 1) / 2;while (child > 0){if (a[parent] < a[child]){Swap(a + parent, a + child);child = parent;parent = (child - 1) / 2;}else{break;}}
}
void AdjustDown(int* a, int parent, int n)
{assert(a);int child = 2 * parent + 1;while (child<n){if (child+1 <n && a[child] < a[child + 1]){child++;}if (a[parent] < a[child]){Swap(a + parent, a + child);parent = child;child = 2 * parent + 1;}else{break;}}
}
  1. 演示一下向下调整法建堆

int main()
{int arr[15] = { 1,4,5,2,7,8,3,4,9,0,4,3,11,6,8 };int size = 15;for (int i = (size - 1 - 1) / 2; i >= 0; i--){AdjustDown(arr, i, size);}return 0;
}
  1. 建堆的核心就在于把AdjustUp与AdjustDown的核心与意义彻底弄清楚

  1. 以后建堆就关注这两个: 数组(完全二叉树)得有+AdjustDown核心奥义


堆排序 O(NlogN)

  1. 堆在我们这边的优点就是说他已经不像之前那样单独的存储数据,他能够做到帮我们去选数

  1. 因此的话,从更加程度而言,它能够帮助我们排序,如果排序的数据量小的话倒还无所谓,我说排序的数据量一大,那么对于性能的要求就非常重要。与我们之前学过的冒泡排序,它的时间复杂度是O(N^2),对堆排序而言的话,它的时间复杂度是O(NlogN)。这两个差异极大

  1. 在堆排序之前的话,需要脑子拎清楚的是,我们现在已经不是在堆着那个结构体里面了,现在我们跟手撕数据结构的那个堆就是说自己手搓的那个堆无关了,现在的话相当于就是对题目中给我的数组(完全二叉树)直接进行建堆然后去进行排序。

首先建堆 [ O(N) 向下调整法 ] 数组得有+AdjustDown核心奥义

  1. 要对数组(完全二叉树)建堆如果你要升序排列,就要去建大根堆;如果你要降序排列,要去建小根堆,无论是大根还是小根,然后这个数组的顺序确定是从后往前依次慢慢确定下来的

  1. 建堆的向下调整法前面已经讲了

其次调堆 [堆顶与数组末尾开始去倒] AdjustDown核心奥义

  1. 当把堆建完之后,接下来就是要去换数据了,这个过程当中的核心核心成员与利器就是AdjustDown,然后每次使用这个函数的时候都需要注意,当前这个堆的数据数量是多少,是每次都要减1减1的哟。

堆排序时间复杂度

  1. 堆排序的话,除了一开始要把原始数据(是数组或者说是完全二叉树)建堆之后,还要去转数据调堆。对于第一步,复杂度是O(N)。

  1. 然后调堆的时间复杂度也是logN*N,用错位相减法减减算算也很快的,或者说你用直观的方法去看一下,对于最后一层而言,如果说你想要确定最后一层(堆排序的话,它是确定的顺序是从数组的从后往前慢慢确定下来的),要确定最后一层的话,就需要不断的把堆顶的数据给往下调整,这就相当于就是说节点最多的层数,它需要调整的次数也是最多。

  1. 因此对于堆排序而言的话,就是说你在一开始对数组(完全二叉树)建堆的时候,无论是用什么方法去建堆,最后总的堆排序时间复杂度都是O(N*logN)

代码

int main()
{int arr[10] = { 1,4,3,5,7,9,8,6,2,0 };int size = 10;//建堆for (int i = (size - 1 - 1) / 2; i >= 0; i--){AdjustDown(arr, i, size);}//调堆int end = size - 1;while (end > 0){Swap(arr + 0, arr + end);AdjustDown(arr, 0, end);end--;}return 0;
}

你会发现,在堆排序里面无论是建堆还是调堆,都与AdjustUp无关


相关文章:

数组(完全二叉树)向下建堆法与堆排序O(N*logN)

TIPS AdjustUp & AdjustDown向上调整AdjustUp与向下调整AdjustDown的参数是一个数组&#xff08;完全二叉树&#xff09;需要进行调整操作的数值的下标/一个数组&#xff08;完全二叉树&#xff09;堆元素个数需要调整操作的数值的下标。实际上就是对完全二叉树当中的某一点…...

Lua require 函数使用

从 Lua 的用户文档中我们知道 require("modName") 函数是用来加载模块的&#xff0c;而如果这个modName已经用require 加载过的&#xff0c;再调用require时&#xff0c;将直接返回模块的值。因为函数首先查找 package.loaded 表&#xff0c; 检测 modName 是否被加载…...

【面试】如何定位线上问题?

这个面试题我在两年社招的时候遇到过&#xff0c;前几天面试也遇到了。我觉得我每一次都答得中规中矩&#xff0c;今天来梳理复盘下&#xff0c;下次又被问到的时候希望可以答得更好。 下一次我应该会按照这个思路去答&#xff1a; 1、如果线上出现了问题&#xff0c;我们更多…...

字节二面,原来我对自动化测试的理解太浅了

如果你入职一家新的公司&#xff0c;领导让你开展自动化测试&#xff0c;作为一个新人&#xff0c;你肯定会手忙脚乱&#xff0c;你会如何落地自动化测试呢&#xff1f; 01 什么是自动化 有很多人做了很长时间的自动化但却连自动化的概念都不清楚&#xff0c;这样的人也是很悲…...

Android11.0 应用升级成功后立即断电重启,版本恢复

问题&#xff1a;客户反馈内置的应用升级成功后立刻断电重启&#xff0c;应用的版本被恢复。 使用adb命令升级客户应用&#xff0c;查看版本显示已更新&#xff0c;/data/system目录下packages.xml和packages.xml中应用版本信息均已更新 C:\Users\dell>adb shell dumpsys …...

关于python常用软件用法:Pycharm 常用功能

人生苦短&#xff0c;我用python 一.Pycharm的基本使用 1.在Pycharm下为你的Python项目配置Python解释器 &#xff08;1&#xff09;.Setting>Project Interpreter>源码资料电子书:点击此处跳转文末名片获取 二.在Pycharm下创建Python文件、Python模块 1.File>New&g…...

SOLIDWORKS你不知道的小技巧

◉ SOLIDWORKS圆弧长度标注点智能标注&#xff0c;再选中该圆弧&#xff0c;然后分别点圆弧的两个端点&#xff0c;点击左键可以标注圆弧长度。◉ SOLIDWORKS强力裁剪剪裁实体中的强劲剪裁&#xff0c;除了可以裁剪实体外&#xff0c;还可以任意延伸实体。◉ SOLIDWORKS转折线转…...

有了HTTP,为啥还要用RPC

既然有 HTTP 请求&#xff0c;为什么还要用 RPC 调用&#xff1f; 一直以来都没有深究过RPC和HTTP的区别&#xff0c;不都是写一个服务然后在客户端调用么&#xff1f; HTTP和RPC最本质的区别&#xff0c;就是 RPC 主要是基于 TCP/IP 协议的&#xff0c;而 HTTP 服务主要是基…...

[leetcode] 动态规划

背包 先啃懂 背包九讲 01背包&#xff0c;即物品有限。 for 物品for 容量&#xff08;倒序&#xff09;P1048 [NOIP2005 普及组] 采药 [ 原题 | 题解 ] P1049 [NOIP2001 普及组] 装箱问题 [ 原题 | 题解 ] P1507 NASA的食物计划 [ 原题 | 题解 ] P1510 精卫填海 [ 原题 | 题…...

科大奥瑞物理实验——热电偶特性及其应用研究

实验名称&#xff1a;热电偶特性及其应用研究 1. 实验目的&#xff1a; 掌握电位差计的工作原理和结构特点&#xff1b;了解温差电偶测温的原理和方法&#xff1b;学会电位差计的使用及注意事项。 2. 实验器材&#xff1a; 电位差计 标准电池 光电检流计 稳压电源 温差电偶…...

Eclips快捷键大全(超详细)

Eclips快捷键大全&#xff08;超详细&#xff09;前言一、常用快捷键二、编辑快捷键三、导航快捷键四、运行和调试快捷键五、重构快捷键六、代码生成快捷键七、项目导航快捷键八、帮助快捷键九、搜索快捷键十、标记快捷键十一、版本控制快捷键十二、其它快捷键前言 本博主将用C…...

整懵了,蚂蚁金服4面成功拿下测开offer,涨薪10k,突然觉得跳槽也不是那么难

蚂蚁的面试挺独特的&#xff0c;每轮面试都没有HR约时间&#xff0c;一般是晚上8点左右面试官来一个电话&#xff0c;问是否能面试&#xff0c;能的话开始面&#xff0c;不能就约一个其他时间。 全程4面&#xff0c;前四面技术面&#xff0c;电话面试&#xff0c;最后一面是HR面…...

C++内存分布malloc-free-new-delete的区别和联系

目录 一、内存分布 1.1内存分布图&#xff1a; 1.2 为什么要将bss和data区分开呢&#xff1f; 1.3 堆和栈有什么区别 二、malloc、free&#xff1b;new、delete 2.1 new和delete是如何实现的&#xff0c;new与malloc的异同处 2.2既然有了malloc/free&#xff0c;C为什么还…...

【华为OD机试 2023最新 】 最多颜色的车辆(C++ 100%)

文章目录 题目描述输入描述输出描述用例题目解析C++题目描述 在一个狭小的路口,每秒只能通过一辆车,假设车辆的颜色只有 3 种,找出 N 秒内经过的最多颜色的车辆数量。 三种颜色编号为0 ,1 ,2 输入描述 第一行输入的是通过的车辆颜色信息 [0,1,1,2] 代表4 秒钟通过的车…...

Linux安全加固

一、重要文件 /etc/passwd #记录本地用户的属性信息&#xff0c;如UID、GID /etc/shadow #存放用户的口令信息 只有系统管理员能查看 /etc/pam.d/system-auth #账户安全配置文件 /etc/login.defs #修改登录的配置文件 /etc/profile …...

Java基础学习(6)

Java基础学习一 字符串1.1 API 与 API文档1.1.1 如何使用帮助文档查找想要导用的方法1.2 String 概述1.3 创建String对象的两种方式第一种第二种1.4 Java常用字符串方法1.4.1 比较1.4.2 字符串通过索引取出1.4.3 取出字符串中的单个字符1.4.4 替换出字符串当中的字符1.4.5 取出…...

【LeetCode】链表练习 9 道题

第一题&#xff1a;移除链表元素 题目描述&#xff1a; 给你一个链表的头节点head和一个整数val&#xff0c;请你删除链表中所有满足Node.val val的节点&#xff0c;并返回新的头节点 。 列表中的节点数目在范围 [0, 10^4] 内1 < Node.val < 500 < val < 50 /…...

轴承远程监控系统解决方案

一、项目背景 随着现代机械设备朝着高集成、高精密度、系统化、自动化的方向发展&#xff0c;在工业生产中一旦机器发生故障&#xff0c;即使局部失灵&#xff0c;都可能导致设备工作失效&#xff0c;甚至造成整个自动化车间停产&#xff0c;从而给工业生产带来巨大的损失。轴承…...

阿里云轻量服务器Workbench root远程连接和一键连接的区别

阿里云轻量应用服务器远程连接支持Workbench root用户连接和Workbench一键连接&#xff0c;Workbench root需要输入root密码&#xff0c;一键连接不需要输入密码&#xff0c;但是也无法获得root权限&#xff0c;阿里云百科来详细说下阿里云轻量应用服务器远程连接说明&#xff…...

带你用纯C实现一个内存池(图文结合)

为什么要用内存池 为什么要用内存池&#xff1f;首先&#xff0c;在7 * 24h的服务器中如果不使用内存池&#xff0c;而使用malloc和free&#xff0c;那么就非常容易产生内存碎片&#xff0c;早晚都会申请内存失败&#xff1b;并且在比较复杂的代码或者继承的屎山中&#xff0c…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...