【Hello Algorithm】堆和堆排序

本篇博客简介: 讲解堆和堆排序相关算法

堆和堆排序

    • 堆的概念
    • 堆的性质
    • 堆的表示形式
    • 堆的增加
    • 删除堆的最大值
  • 堆排序
    • 堆排序思路
    • 时间复杂度为N的建堆方法
    • 已知一个近乎有序的数组 使用最佳排序方法排序

堆的概念

这里注意!!! 这里说的堆和操作系统里面的堆没有半点关系!!!

如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为 小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

上面这个就是官方的解释了

但是要是我们用通俗的话来说

就是这样子的

大堆 就是所有的父节点都大于等于子节点的堆

小堆 就是所有的子节点都小于等于父节点的堆

如图

在这里插入图片描述

堆的性质

  1. 堆总是一棵完全的二叉树

  2. 堆中某个节点的值总是不大于或者不小于其父节点的值

什么是完全二叉树呢

它要么是一颗满二叉树 要么它正在变满的路上

堆的表示形式

我们一般使用一个数组来从存储结构上表示一个堆 而堆在逻辑结构上表示一颗二叉树

具体的示例如下

假设我们现在有如下的一个数组

在这里插入图片描述

现在要将其转化为一颗完全二叉树

我们在上文说过一句话 堆要么是一颗满二叉树 要么在变成满二叉树的路上

所以说 我们只要按照满二叉树的形式构造一颗二叉树 到最后构造出来的一定是一颗完全二叉树

而满二叉树每一层的节点格式是确定的 所以说我们从第一层开始 依次拿一个数字 两个 数字 四个数字… 构造即可

在这里插入图片描述

从上面的构造中 我们能发现这样子的一个规律

我们现在假设 i 为数组的下标 那么根据完全二叉树的特征 我们可以得出以下结论

如果i对应的节点左孩子 右孩子 父亲节点存在的话

  • i 对应节点的左孩子节点下标一定是 2*i+1
  • i 对应节点的右孩子节点下标一定是 2*i+2
  • i 对应节点的父节点下标一定是 (i-1)/2

堆的增加

我们假设现在有一个空数组 我们要用这个数组构建出一个大堆

现在依次插入数字 10 8 6 那么形成的逻辑结构如下

在这里插入图片描述

目前二叉树是一个完全二叉树 并且符合大堆的性质

可是如果我们下一个数字插入 12 那么我们就破坏了这个大堆了

插入数字 12 之后就会出现子节点大于父节点的情况 这明显和我们上面讲的大堆的性质不符

在这里插入图片描述

此时为了让我们的大堆继续生效 我们就需要将出问题的节点向上调整

而又根据我们上面将的性质 一个节点通过公式 (i-1)/2 就能够找到它的父节点

之后就是与父节点比大小 如果子节点大就交换它们的位置

在这里插入图片描述

可是我们交换一次之后并不能保证这就是个大堆了 所以说向上调整要一直调整到根节点或者说比较不过父节点为止

在这里插入图片描述

删除堆的最大值

在这里插入图片描述
我们想要删除堆中的一个数据 还要不改变这个堆的结构 这个时候怎么办呢

我们这里给出一种很巧妙的解法

我们先将最前面的元素和最后面的元素交换位置

然后再删除掉堆最后面的元素

之后开始向下调整这个堆

如上图所示

如果说一个堆有 14 个元素 其中下标为7的为止的值被修改成了一个未知的值 我们应该如何修改使得该堆正常

其实思路很简单 它的值变化只有三种可能 变大 变小 不变

不变的情况我们不考虑 如果变大或者变小 其他位置的值是不发生改变的

我们只需要对于该位置执行两个操作

  • 向上调整
  • 向下调整

如果向上调整调用成功 则说明上面的树已经恢复正常了 而下面的树根本就没变 所以说这个堆整体就正常了 我们也不不需要向下调整了

如果我们向上调整之后 这个堆没有变化 那一定说明上面没问题 下面出问题了 此时调用向下调整即可

堆排序

我们C++中是实现了堆这种数据结构的 具体内容可以参考我的这篇博客

此外这篇博客中还详细讲解了 向上调整和向下调整的算法 优先级队列

堆排序的时间复杂度

进行堆插入的过程要调用向上调整函数

我们假设 堆中有N的元素 那么这个堆的逻辑二叉树结构就有LogN层高

所以说我们最多最多要比较LogN次 因为每一次插入的时间复杂度都是LogN

如果我们插入N个数 那么时间复杂度就是 N*LogN了

堆排序思路

如果说现在给我们一个无序的数组 要让我们对于这个数组从小到大排序

那么我们可以构建一个小堆作为中间的数据结构

方法如下

  • 首先将数组中的数组遍历一遍 并且放入到优先级队列中
  • 优先级队列的根节点一定是最小值 所以我们每次拿数据一定保证是比后面值要小的
  • 我们从0下标开始填数据 每次下标加1并且填写根节点的值 直到堆中没有数据为止

时间复杂度为N的建堆方法

我们如果每次都是在最后插入数据 不停向上调整的话 建堆的时间复杂度是趋近于N*LogN的

但是在一定条件下 我们的建堆时间复杂度可以达到 N 需要达到的条件如下

  • 我们要知道数组的大小
  • 我们要知道所有需要插入的数字

建堆思路如下

  • 我们从最后一层最后一个结点开始建堆 使用向下调整的算法
  • 调整完最后一层之后我们继续从上一层的最后一个节点开始 插入数据 使用向下调整的算法
  • 重复上面的步骤

下面是我的笔记分析

在这里插入图片描述

已知一个近乎有序的数组 使用最佳排序方法排序

我们现在已知一个几乎有序的数组 请选择一个合适的排序方法将其排序 并说明时间复杂度是多少

  • 几乎有序的指的是 如果把数组排好序的话 每个元素移动的距离一定不超过K

解决这个问题我们的思路还是使用堆排序

我们假设K值为5

那么我们现在建立一个小堆 堆的大小为6 那么我们可以肯定的说 这个小堆的根节点就是这个数组的最小值

因为这六个数中肯定会有数组的最小值 而我们排序获取了这六个数的最小值 那么该值就一定是数组的最小值了

之后我们数组中的第二小值肯定在第2~7个数字中 我们只需要将数组的后一个元素插入小堆中即可找到

之后按照上面的方法 排一个插一个 排一个插一个

我们一共排了N个数字 每个数字最坏的情况要交换LogK次

所以说 最坏的时间复杂度为 NLogK 当K足够小的时候 时间复杂度可以近似看作NLogK

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UG\NX二次开发 使用BlockUI设计对话框时,如何设置默认的开发语言?

文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,C\C++,Qt-CSDN博客 简介: NX二次开发使用BlockUI设计对话框时,如何设置默认的代码语言? 效果: 方法: 依次打开“文件”->“实用工具”->“用户默认设置”->“用户界面”->“操作记录”->“…

【WSN无线传感器网络恶意节点】使用 MATLAB 进行无线传感器网络部署研究

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

React 全栈体系(三)

第二章 React面向组件编程 四、组件三大核心属性3: refs与事件处理 1. 效果 需求: 自定义组件, 功能说明如下: 点击按钮, 提示第一个输入框中的值当第2个输入框失去焦点时, 提示这个输入框中的值 2. 理解 组件内的标签可以定义ref属性来标识自己 3. 编码 3.1 字符串形式…

Gradle 如何配置全局 mavenCentral()

我们都知道 Gradle 会使用 Maven 的中央仓库。 在 Gradle 的配置文件中&#xff0c;通常有一个 mavenCentral() 如果我们想把 mavenCentral() 的仓库地址全局替换掉别的仓库地址的话。 我们可以在 C:\Users\yhu\.gradle 目录下创建一个 init.gradle 文件。 文件中的代码为&a…

中国移动秋招攻略,网申测评和面试

中国移动秋招简介 按照往年的惯例来看&#xff0c;移动会在每年的8月份发布相关秋招信息&#xff0c;紧接着考生并进行网申&#xff0c;面试的时间跨度也非常的长&#xff0c;大概是9~12月份。整个招聘流程&#xff0c;包括投递简历网申&#xff0c;笔试测评&#xff0c;面试录…

在项目中快速搭建机器学习的流程

在软件开发领域&#xff0c;机器学习框架发挥着关键作用&#xff0c;为开发人员提供强大的人工智能工具、库和算法&#xff0c;以有效地利用机器学习的潜力。从本质上讲&#xff0c;机器学习使计算机能够从数据中学习并做出预测或决策&#xff0c;而无需明确编程。 机器学习框…

idea 对JavaScript进行debug调试

文章目录 1.新增 JavaScript Debug 配置2.配置访问地址3.访问url. 打断点测试 前言 : 工作中接手别人的前端代码没有注释&#xff0c;看浏览器的network或者console切来切去&#xff0c;很麻烦&#xff0c;可以试试idea自带的javscript debug功能。 1.新增 JavaScript Debug 配…

芯科科技推出专为Amazon Sidewalk优化的全新片上系统和开发工具,加速Sidewalk网络采用

芯科科技为Sidewalk开发提供专家级支持 中国&#xff0c;北京 - 2023年8月22日 – 致力于以安全、智能无线连接技术&#xff0c;建立更互联世界的全球领导厂商Silicon Labs&#xff08;亦称“芯科科技”&#xff0c;NASDAQ&#xff1a;SLAB&#xff09;今日在其一年一度的第四…

微信支付

文档地址&#xff1a;https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter9_1 封装的工具类 package com.qf.fmall.utils;import cn.hutool.core.util.XmlUtil; import cn.hutool.http.HttpRequest; import org.apache.shiro.crypto.hash.Md5Hash;import java.util.…

情人节特别篇:用c++弹奏音乐“海阔天空”与“孤勇者”

W...Y的主页 &#x1f495; 代码库分享 &#x1f60a; 目录 孤勇者 海阔天空 今天是2023年8月22日七夕情人节&#xff0c;但是对我来说就是再普通不过的日子。我相信有很多人期待这一天的到来&#xff0c;和自己的对象出去享受快乐时光。但是我只有一个人独孤的度过短暂的时…

freertos之任务调度算法

介绍 所谓调度算法&#xff0c;就是怎么确定哪个就绪态的任务可以切换为运行状态。 通过配置文件FreeRTOSConfig.h的三个配置项来配置调度算法&#xff1a;configUSE_PREEMPTION &#xff08;是否抢占&#xff09; configUSE_TIME_SLICING &#xff08;是否轮转&#xff09; c…

分布式事务(7):SpringCloud2.0整合LCN

目前LCN版本已经升级为4.0了,但是官方没有SpringCloud2.0的demo案例。 因为LCN本身是开源的,有些大神对LCN框架源码做修改,可以支持SpringCloud2.0版本。 下载地址:https://download.csdn.net/download/u013938578/88251904 1 下载LCN服务端源码 https://download.csdn.…

day-27 代码随想录算法训练营(19)回溯part03

39.组合总和 分析&#xff1a;同一个数可以选多次&#xff0c;但是不能有重复的答案&#xff1b; 思路&#xff1a;横向遍历&#xff0c;纵向递归&#xff08;不同的是递归的时候不需要跳到下一个位置&#xff0c;因为同一个数可以选多次&#xff09; class Solution { publ…

基于python+pyqt的opencv汽车分割系统

目录 一、实现和完整UI视频效果展示 主界面&#xff1a; 识别结果界面&#xff1a; 查看分割处理过程图片界面&#xff1a; 二、原理介绍&#xff1a; 加权灰度化 ​编辑 二值化 滤波降噪处理 锐化处理 边缘特征提取 图像分割 完整演示视频&#xff1a; 完整代码链…

4.14 tcp_tw_reuse 为什么默认是关闭的?

开启 tcp_tw_reuse 参数可以快速复用处于 TIME_WAIT 状态的 TCP 连接时&#xff0c;相当于缩短了 TIME_WAIT 状态的持续时间。 tcp_tw_reuse 是什么&#xff1f; TIME_WAIT 状态的持续时间是 60 秒&#xff0c;这意味着这 60 秒内&#xff0c;客户端一直会占用着这个端口。端…

springboot定时任务:同时使用定时任务和websocket报错

背景 项目使用了websocket,实现了消息的实时推送。后来项目需要一个定时任务&#xff0c;使用org.springframework.scheduling.annotation的EnableScheduling注解来实现&#xff0c;启动项目之后报错 Bean com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration of t…

11.Oracle中rollup函数详解

【基本介绍】 【格式】&#xff1a;group by rollup(字段1,字段2,字段3,...,字段n) 【说明】&#xff1a;rollup主要用于分组汇总&#xff0c;如果rollup中有n个字段&#xff0c;则会分别按【字段1】、【字段1,字段2】&#xff0c;【字段1,字段2,字段3】&#xff0c;...&#…

uniapp,使用canvas制作一个签名版

先看效果图 我把这个做成了页面&#xff0c;没有做成组件&#xff0c;因为之前我是配合uview-plus的popup弹出层使用的&#xff0c;这种组件好像是没有生命周期的&#xff0c;第一次打开弹出层可以正常写字&#xff0c;但是关闭之后再打开就不会显示绘制的线条了&#xff0c;还…

【Linux应用部署篇】在CSDN云IDE平台部署Etherpad文档编辑器

【Linux应用部署篇】在CSDN云IDE平台部署Etherpad文档编辑器 一、CSDN云IDE平台介绍1.1 CSDN云IDE平台简介1.2 CSDN云IDE平台特点 二、本次实践介绍2.1 本次实践介绍2.2 Etherpad简介 三、登录CSDN云IDE平台3.1 登录CSDN开发云3.2 登录云IDE3.3 新建工作空间3.4 进入工作空间 四…

Spring(aop介绍,底层实现,jdk代理,cglib代理)

02-aop简介-aop的作用及其优势_哔哩哔哩_bilibili 122 1、Spring的aop介绍 1.1aop是一种技术&#xff0c;aop是在运行之间执行的&#xff0c;他可以完成程序功能之间的松耦合&#xff0c;动态代理的作用也等同于Aop的作用&#xff1a;他提供了相应的封装&#xff0c;Aop是面向…