算法-堆结构和堆排序

文章目录

    • 本节大纲
    • 1. 堆结构
    • 2. 堆排序
    • 本节的代码实现合集

本节大纲

在这里插入图片描述

1. 堆结构

堆结构是为集合类里面的优先级队列来服务的
优先级队列其实就是顺序存储的二叉树结构, 我们的底层的源码里面是没有链式存储的二叉树的,二叉树的实现的细节是通过我们的数组来模拟实现的
底层的实现细节 :
数组加上一个usedSize就可以实现一个顺序存储的二叉树结构

堆的调整
堆的调整分为向上调整与向下调整, 请注意, 堆的每次调整都是基于其中
的某一个元素破坏了堆的结构, 但是其他的堆的性质没有发生改变的情况下,所以请注意, 一定是一个元素

堆的向上调整 : 该调整不用传入终止条件, 因为根节点的下标就是天然的终止条件, 从下面的条件里面我们可以发现, 根节点的父亲节点就是其本身

代码实现如下:

 /*** 堆的调正是整个堆操作的最重要的步骤(这里我们默认实现的是大根堆)* --> 根据之前我们学习堆结构时期的困惑, 不管是向上调整还是向下调整,都是因为只有某个位置的元素破坏了堆的结构, 切记是一个! ! !** @param nums : 传入的需要调整的数组* @param i    : 待调整元素的下标*             向上调整不需要设置终点位置, 因为就是根节点自己 当 i == 0是时, (i - 1) / 2 == 0,自动跳出循环*/private void heapInsert(int[] nums, int i) {while (nums[i] > nums[(i - 1) / 2]) {swap(nums, i, (i - 1) / 2);i = (i - 1) / 2;}}

堆的向下调整 : 这个就跟向上调整不一样了, 这个没有天然的终止条件, 可以认为的传入终止条件…

代码实现如下

/*** 这里跟上面的向上调整的类似的,我们都是只有其中的一个元素破坏了堆的结构(默认实现大根堆)*     之前我们没有理解向上调整跟向下调整的原因就是,我们忽略了只有一个元素破坏了堆结构这一条件* @param nums : 待调整的数组* @param i    : 待调整的元素的下标* @param end  : 结束位置*/private void heapify(int[] nums, int i, int end) {int l = 2 * i + 1; //先把孩子下标打到左孩子的位置;while (l < end) {//下面这句话的代码逻辑是 --> 找到最大孩子的孩子下标int best = l + 1 < end && nums[l + 1] > nums[l] ? l + 1 : l;//下面这句话的代码逻辑是 --> 比较最大的孩子跟父节点best = nums[i] < nums[best] ? best : i;if (best == i) {break;}swap(nums, best, i);i = best;l = 2 * i + 1;}}

堆的调整的时间复杂度分析 --> 堆的调整的时间复杂度是O(LogN), 依据的是二叉树的树的高度

2. 堆排序

堆排序其实就是堆结构的应用, 原理就是(这里按照升序分析) :
传入一个数组然后建堆(可以从顶部到底部建堆, 也可以反着来)
两种建堆的时间复杂度是不一样的, 等一下详细的说明一下
堆建立完毕之后, 我们将顶部元素跟最后一个元素进行交换,
控制最后一个范围的位置, 然后向下调整, 循环下去…

堆排序的原理就是上面所说的那样, 实现的逻辑见下
从顶部向下建堆

 //堆排序的从上往下建堆的实现方式public void heapSort(int[] nums){//首先需要的是建堆int len = nums.length;for (int i = 0; i < len; i++) {heapInsert(nums,i);}//建堆完毕之后, 进行堆排序的过程while(len > 0){swap(nums,0,--len);heapify(nums,0,len);}}

上面的从上往下建堆的时间复杂度是O(NLogN)
这个数学证明我们就不说了
大概原理就是 : log1 + log2 + log3 +…+ logN 收敛于N
LogN
但是下面进行交换排序的时间复杂度是一定是O(N*LogN)

堆排序的从底部向上建堆的代码实现

  //从顶部向下建堆的方式public void heapSort1(int[] nums) {//建堆成功for (int pra = (nums.length - 1 - 1) / 2; pra >= 0; pra--) {heapify(nums,pra,nums.length);}//建堆完毕之后, 进行堆排序的过程int len = nums.length;while (len > 0) {swap(nums, 0, --len);heapify(nums, 0, len);}}

为什么说从底部向上建堆的时间复杂度更好
每一层累加起来其实是一个差比数列求和公式
下图左边的是看的节点的规模, 右侧的是向下调整的层数

在这里插入图片描述

本节的代码实现合集


/*** 下面我们自己实现一个堆*/
class Heap {int[] elem;int usedSize;private static final int DEFAULT_CAPACITY = 11;//底层默认是11//提供两个构造方法public Heap() {this(DEFAULT_CAPACITY);}public Heap(int initCapacity) {elem = new int[initCapacity];}/*** 建堆的时候, 我们尝试直接用数组来模拟实现大根堆* 之前我们一直不理解, 为什么建堆要从后往前逐一的向下调整,* 现在明白了,因为这样才能保证每次调整完毕之后下一次调整的时候只有一个顶部元素是不确定的** @param nums*/public Heap(int[] nums) {//空间不够就进行扩容(我们现在实现的这个只是简单的版本,可能会因为空间不足的bug)this(DEFAULT_CAPACITY);if (elem.length <= nums.length) {this.elem = Arrays.copyOf(elem, elem.length * 2);}//进行拷贝元素for (int i = 0; i < nums.length; ++i) {elem[i] = nums[i];}usedSize = nums.length;//下面就进行建堆的过程for (int parent = (usedSize - 1 - 1) / 2; parent >= 0; --parent) {heapify(elem, parent, usedSize);}}/*** 堆的调正是整个堆操作的最重要的步骤(这里我们默认实现的是大根堆)* --> 根据之前我们学习堆结构时期的困惑, 不管是向上调整还是向下调整,都是因为只有某个位置的元素破坏了堆的结构, 切记是一个! ! !** @param nums : 传入的需要调整的数组* @param i    : 待调整元素的下标*             向上调整不需要设置终点位置, 因为就是根节点自己 当 i == 0是时, (i - 1) / 2 == 0,自动跳出循环*/private void heapInsert(int[] nums, int i) {while (nums[i] > nums[(i - 1) / 2]) {swap(nums, i, (i - 1) / 2);i = (i - 1) / 2;}}/*** 这里跟上面的向上调整的类似的,我们都是只有其中的一个元素破坏了堆的结构(默认实现大根堆)* 之前我们没有理解向上调整跟向下调整的原因就是,我们忽略了只有一个元素破坏了堆结构这一条件** @param nums : 待调整的数组* @param i    : 待调整的元素的下标* @param end  : 结束位置*/private void heapify(int[] nums, int i, int end) {int l = 2 * i + 1; //先把孩子下标打到左孩子的位置;while (l < end) {//下面这句话的代码逻辑是 --> 找到最大孩子的孩子下标int best = l + 1 < end && nums[l + 1] > nums[l] ? l + 1 : l;//下面这句话的代码逻辑是 --> 比较最大的孩子跟父节点best = nums[i] < nums[best] ? best : i;if (best == i) {break;}swap(nums, best, i);i = best;l = 2 * i + 1;}}private void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}/*** 下面是简单的删除操作*/public void poll() {swap(elem, 0, usedSize - 1);usedSize--;heapify(elem, 0, usedSize);}/*** 一些其他的操作*/public int peek() {return elem[0];}//展示的操作public void show() {for (int i = 0; i < usedSize; i++) {System.out.print(elem[i] + " ");}System.out.println();}//堆排序的从上往下建堆的实现方式public void heapSort(int[] nums) {//首先需要的是建堆int len = nums.length;for (int i = 0; i < len; i++) {heapInsert(nums, i);}//建堆完毕之后, 进行堆排序的过程while (len > 0) {swap(nums, 0, --len);heapify(nums, 0, len);}}//从顶部向下建堆的方式public void heapSort1(int[] nums) {//建堆成功for (int pra = (nums.length - 1 - 1) / 2; pra >= 0; pra--) {heapify(nums,pra,nums.length);}//建堆完毕之后, 进行堆排序的过程int len = nums.length;while (len > 0) {swap(nums, 0, --len);heapify(nums, 0, len);}}public static void main(String[] args) {int[] nums = new int[]{5, 8, 6, 7, 3, 1, 9, 2, 7, 1, 4, 6};Heap heap = new Heap(nums);heap.heapSort1(nums);System.out.println(Arrays.toString(nums));}
}

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

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

相关文章

TFTP服务器

软件&#xff0c;客户端&#xff0c;服务器。是简单的文件传输文件。 1.TFTP服务器介绍 是简单的文件传输协议&#xff0c;是tcp/IP协议的一个用来在客户端与服务器之间进行简单文件传输的协议。端口号为69。每个服务器都有自己都端口号。 2.TFTP文件传输特点 3. 二:TFTP环境…

c++异常处理exception

// c中的异常处理 // 1.throw &#xff1a; 专门用于抛出异常&#xff0c;做出提示 // 2.try &#xff1a; 尝试运行可能会异常的代码 // 3.catch &#xff1a; 用于接收前面跑出来的异常并进行解决// 执行循序为: // try // { // throw ...; // 执行的代码中必须直接或者…

VRTK4教程 二:基本追踪

文章目录 untiyXR和UnityXRPluginFramwork使用方法&#xff1a; TrackedAlias使用方法使用技巧 untiyXR和UnityXRPluginFramwork 这两个用于跟踪头盔位置&#xff0c;其中UnityXR使用的是旧版API&#xff0c;另一个是新版API&#xff0c;两个我我们选一个即可 使用方法&#…

6.3 Go 结构体(Struct)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

【计算机毕设】SpringBoot校园资料分享平台的设计与实现 - 源码免费(私信领取)

免费领取源码 &#xff5c; 项目完整可运行 &#xff5c; v&#xff1a;chengn7890 诚招源码校园代理&#xff01; 1. 研究目的 本项目旨在设计并实现一个基于SpringBoot的校园资料分享平台&#xff0c;以满足学生在学习过程中对资料分享和获取的需求。具体目标包括&#xff1a…

Java学习笔记 集合的使用

在实际的项目中开发过程中&#xff0c;会有很多的对象&#xff0c;如何高效、方便的管理这些对象&#xff0c;是影响程序性能与可维护性的重要环节。在Java语言中为这个问题提供了一套完美的解决方案&#xff0c;也就是接下来要介绍的集合框架。 1.1 集合框架的结构 从Collect…

都说美国去工业化了,那美国人都做什么工作啊?

美国&#xff0c;这个全球经济的重要参与者&#xff0c;经历了一场深刻的变革——去工业化。这一过程意味着&#xff0c;曾经以制造业为荣的美国&#xff0c;逐渐将重心转移到了其他领域。那么&#xff0c;美国人都做什么工作呢&#xff1f;让我们走近这位“经济体巨人”&#…

MySql 查询缓存

前言 MySQL的查询缓存&#xff08;Query Cache&#xff09;是一个在内存中存储SELECT语句及其结果集的机制&#xff0c;目的是避免对相同的查询进行重复的解析、编译和执行&#xff0c;从而提高数据库性能。 Mysql 结构图如下&#xff1a; 查询缓存的工作流程大致如下&#…

Java中连接Mongodb进行操作

文章目录 1.引入Java驱动依赖2.快速开始2.1 先在monsh连接建立collection2.2 java中快速开始2.3 Insert a Document2.4 Update a Document2.5 Find a Document2.6 Delete a Document 1.引入Java驱动依赖 注意&#xff1a;启动服务的时候需要加ip绑定 需要引入依赖 <dependen…

【魅力网页的背后】:CSS基础魔法,从零打造视觉盛宴

文章目录 &#x1f680;一、css基础知识⭐1. 认识css &#x1f308;二、选择器初级❤️id与class命名 &#x1f680;一、css基础知识 ⭐1. 认识css 概念 CSS(英文全称&#xff1a;Cascading Style Sheets)&#xff0c;层叠样式表。它是网页的装饰者&#xff0c;用来修饰各标签…

QT 使用信号和槽,让QLabel的内容实时与QLineEdit同步,类似vue框架的双向绑定

在窗口里放置一个单行文本编辑器&#xff08;QLineEdit&#xff09;和一个标签控件&#xff08;QLabel&#xff09;&#xff0c;实现的效果就是当编辑器的内容被编辑时&#xff0c;标 签控件同步显 示编辑控件里的内容 1&#xff09;当 lineEdit 控件被用户编辑时&#xff0c;它…

无人机路径规划:基于鸽群优化算法PIO的无人机三维路径规划MATLAB代码

一、无人机模型介绍 无人机三维航迹规划_无人机航迹规划-CSDN博客 二、部分代码 close all clear clc warning (off) global model global gca1 gca2 gca3 gca4 model CreateModel(); % Create search map and parameters load(BestPosition5.mat); load(ConvergenceCurve5…

四足机器人步态仿真(三)四足机器人基础步态仿真

观前提醒&#xff0c;本章主要内容为分析四足机器人步态实现和姿态控制&#xff0c;碰撞体积等程序 步态效果&#xff1a; 一、完整代码如下 # -*- coding: utf-8 -*-import pybullet as pimport timeimport numpy as npp.connect(p.GUI)p.createCollisionShape(p.GEOM_PLANE…

xLSTM: Extended Long Short-Term Memory

更多内容&#xff0c;请关注微信公众号&#xff1a;NLP分享汇 原文链接&#xff1a;xLSTM: Extended Long Short-Term Memory 论文链接&#xff1a;https://arxiv.org/pdf/2405.04517 为什么要在27年后提出新的LSTM呢&#xff1f; LSTM&#xff08;长短期记忆网络&#xff09…

Java 生成二维码底下带content

直接上代码&#xff1a;效果如下图 需引入 zxing生成二维码包 <dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.3.3</version></dependency><dependency><groupId>com.…

vue不同页面切换的方式(Vue动态组件)

v-if实现 <!--Calender.vue--> <template><a-calendar v-model:value"value" panelChange"onPanelChange" /></template> <script setup> import { ref } from vue; const value ref(); const onPanelChange (value, mod…

【Matplotlib作图-3.Ranking】50 Matplotlib Visualizations, Python实现,源码可复现

目录 03 Ranking 3.0 Prerequisite 3.1 有序条形图(Ordered Bar Chart) 3.2 棒棒糖图(Lollipop Chart) 3.3 点图(Dot Plot) 3.4 斜率图(Slope Chart) 3.5 杠铃图(Dumbbell Plot) References 03 Ranking 3.0 Prerequisite Setup.py # !pip install brewer2mpl import n…

FJSP:波搜索算法(WSA)求解柔性作业车间调度问题(FJSP),提供MATLAB代码

详细介绍 FJSP&#xff1a;波搜索算法(Wave Search Algorithm, WSA)求解柔性作业车间调度问题&#xff08;FJSP&#xff09;&#xff0c;提供MATLAB代码-CSDN博客 完整MATLAB代码 FJSP&#xff1a;波搜索算法(WSA)求解柔性作业车间调度问题&#xff08;FJSP&#xff09;&…

coredns 被误删了,可以通过重新应用 coredns 的 Deployment 或 DaemonSet 配置文件来恢复

如果 coredns 被误删了&#xff0c;可以通过重新应用 coredns 的 Deployment 或 DaemonSet 配置文件来恢复。以下是恢复 coredns 的步骤&#xff1a; 1. 下载 coredns 配置文件 你可以从 Kubernetes 的官方 GitHub 仓库下载 coredns 的配置文件。以下是下载并应用配置文件的步…

快速排序(排序中篇)

1.快速排序的概念及实现 2.快速排序的时间复杂度 3.优化快速排序 4.关于快速排序的细节 5.总代码 1.快速排序的概念及实现 1.1快速排序的概念 快速排序的单趟是选一个基准值&#xff0c;然后遍历数组的内容把比基准值大的放右边&#xff0c;比基准值小的放在左边&#xf…