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

(手撕)数据结构--->堆

文章内容

   

目录

        一:堆的相关概念与结构

        二:堆的代码实现与重要接口代码讲解


让我们一起来学习:一种特殊的数据结构吧!!!!

        一:堆的相关概念与结构

                在前面我们已经简单的学习过了二叉树的链式存储结构了,那么二叉树的顺序存储结构是啥呢?其实二叉树的顺序存储结构我们一般将他叫做

                二叉树为啥有两种形式的存储结构呢?因为堆是一种特殊的二叉树,它特殊的地方在于它的逻辑结构实际上是一颗完全二叉树,在物理结构上我们一般用数组来表示堆的结构,而如果不是完全二叉树我们一般不会用数组成为二叉树的结构,因为假如不是完全二叉树那么我们数组可能会浪费大量的空间。

        用数组作为二叉树的结构的时候我们必须要知道的双亲结点与子节点的下标关系为:

        leftchild=parent*2+1;

        rightchild=parent*2+2;

        parent=(child-1)/2;(child可以是左孩子也可以是右孩子)

        如图:完全二叉树与非完全二叉树在使用顺序存储结构的区别:

                

        在这里就能看出当结构不同时,我们需要采取不同的形式进行表示。

          总结:堆在逻辑结构上是一棵完全二叉树,在物理结构上是一个数组。对于非完全二叉树我们不适用数组的结构表示二叉树。

        


       堆的两种形式(判断数组是不是堆的方式)

        大堆:树中所有的父亲结点都大于或等于孩子结点,且根节点的值是堆中最大的数据。

        小堆:树中所有的父亲结点都小于或等于孩子结点,且根节点的值是堆中最小的数据。

        这也引出了堆的特点:1:堆中某个结点的值总是不大于或不小于父亲结点的值。

                                             2:堆总是一棵完全二叉树。

                                                        


        二:堆的代码实现与接口的讲解

        由于堆所具有的特点我们定义堆的结构为一个数组,与我们的顺序表,栈的结构类似。

        代码:


typedef int HeapDataType;typedef struct Heap
{HeapDataType* a;int Size;int Capacity;
}HP;

        接下来就是我们熟悉的接口了,一些不难理解的接口我就直接跳过,对其它类型的接口进行讲解。

        初始化堆:其实这个接口有两种初始化的代码:1:就是不开辟空间,等我们实际插入数据的时候来考虑增容和开辟空间。2:是传入一个数组然后将这个数组里面的值拷贝到我们需要开辟的空间当中。

        代码如下:

        

void InitHeap(HP* php)
{assert(php);php->a = NULL;php->Size = php->Capacity = 0;
}

       堆的销毁:直接销毁我们动态开辟的空间。

        代码如下:

void DestoryHeap(HP* php)
{assert(php);free(php->a);php->a = NULL;php->Capacity = php->Size = 0;
}

        接下来我们先讲两个重要的关于堆的算法向上调整算法与向下调整算法

        首先这两个算法的时间复杂度都是log(N)

        这两个算法在建堆的时候作用很大

        我们先讲解

        向上调整算法

                 前提:我们所插入的值前面的结构必须是堆

                接下来我们通过图的方式来讲解这个算法的工作原理

                        

        代码实现:

        

void AdjustUp(HeapDataType* a, int child)
{int parent = (child - 1) / 2;//交换的过程while (child>0){if (a[child] < a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

        总结算法思想:以建大堆为列,将插入的值与双亲进行比较,如果插入的值大于它的双亲的值,那么就交换孩子与双亲,可能我们插入的值非常大,那么可能会到达根节点所以我们使用循环来进行完成,最坏的情况就是我们要向上调整高度次,而完全二叉树的高度我们之前也算过,所以时间复杂度为:log(N);

        向下调整算法 

                   使用前提:左右子树都是堆

               简单图解向下调整算法:

                 

                代码如下:

                

void AdjustDown(HeapDataType* a, int n, int parent)
{int child = parent * 2 + 1;while (child < n){//找小的那个孩子if (child+1<n && a[child] >a[child + 1] ){child++;}if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}

        代码是按小堆而写的        

        注意:这里我们需要考虑到一种特殊的情况,就是当我们孩子结点为最后一个结点的时候那么我们对下标为child+1的结点访问时会越界,而且我们在判断左右孩子谁小的时候我们不需要假定左孩子小这样会有几种情况且很麻烦,所以我们先假定要左孩子小,每次在判断孩子与双亲结点谁小的前面,先拿左孩子右有孩子相互比较,然后我们取小的就行。

        总结算法思想:将父亲结点与孩子结点中小的结点进行比较,然后按照时大堆还是小堆的逻辑进行相互的比较,当孩子结点为叶子结点的时候循环终止。

        插入接口:要保证插入之后我们的堆还是原来的大小堆。

        思想:我们先尾插一个值,然后将这个值进行向上调整,且每次在插入之前我们都需要进行扩容逻辑的判断。

                 代码如下:

                

void PushHeap(HP* php, HeapDataType x)
{assert(php);//先尾插到数组中去//先判断空间是否足够if (php->Capacity == php->Size){int newcapacity = php->Capacity == 0 ? 4 : php->Capacity * 2;HeapDataType* tmp = (HeapDataType*)realloc(php->a, sizeof(HeapDataType) * newcapacity);if (tmp == NULL){perror("realloc fail:");exit(-1);}php->a = tmp;php->Capacity = newcapacity;}php->a[php->Size] = x;AdjustUp(php->a, php->Size);php->Size++;
}

        总结:扩容,插入,向上调整,这几个步骤就能将这个接口给实现。

        

        堆的删除接口:这个接口需要借助向下调整算法来解决

                接口作用,能够将二叉树中最大或最小的结点值给删除,让第二大或第二小结点的值展示出来。

        算法思想:我们并不是通过移动空间来将二叉树中根节点的值给删除,因为顺序表的尾插的时间效率非常的大,所以我们一般时首先将根节点的值与最后一个值进行交换,然后再将交换后的结点进行向下调整,这样做可以得到第二大或小的值。

        代码:

        

void PopHeap(HP* php)
{assert(php);//得有元素才能删除assert(php->Size > 0);//删除的步骤//1先将根结点与尾结点交换,在删除最后一个结点Swap(&php->a[0], &php->a[(php->Size) - 1]);--(php->Size);//2在进行向下调整AdjustDown(php->a, php->a[0],0);
}

        总结:在删除之前我们还需要看我们的堆是否含有结点,然后在交换,向下调整,就可以完成这个接口了。

        这个接口与判空接口和取堆顶接口,能让我们对我们的数据打印出来是升序的或者是降序的。

        取堆顶元素的接口

                思想:直接返回数组中元素下标为0的值就行

        代码:

        

HeapDataType HeapTop(HP* php)
{assert(php);assert(php->Size > 0);return php->a[0];
}

         判断堆有多少个元素的接口

        直接return size就行

        

int HeapSize(HP* php)
{assert(php);return php->Size;
}

        堆的判空:只需要看size为不为0就行

        

bool HeapEmpty(HP* php)
{assert(php);return php->Size == 0;
}


        本章结束!!!欢迎大家的耐心观看

        

相关文章:

(手撕)数据结构--->堆

文章内容 目录 一&#xff1a;堆的相关概念与结构 二&#xff1a;堆的代码实现与重要接口代码讲解 让我们一起来学习:一种特殊的数据结构吧&#xff01;&#xff01;&#xff01;&#xff01; 一&#xff1a;堆的相关概念与结构 在前面我们已经简单的学习过了二叉树的链式存储结…...

[运维|数据库] MySQL 中的COLLATE在 PostgreSQL如何表示

在 PostgreSQL 中&#xff0c;字符集&#xff08;collation&#xff09;和排序规则&#xff08;collation order&#xff09;的概念与 MySQL 类似&#xff0c;但语法和用法略有不同。在 PostgreSQL 中&#xff0c;字符集和排序规则通常是数据库、表或列级别的设置&#xff0c;而…...

【Linux】tar 与 zip 命令

tar 命令 tar 本质上只是一个打包命令&#xff0c;可以将多个文件或者文件夹打包到一个 tar 文件中&#xff0c;结合其他的压缩程序再将打包后的档案文件压缩。 所以看到 .tar.gz, .tar.bz2, .tar.xz 等等文件其实是 tar 文件之后进行 Gzip, Bzip2, XZ 压缩之后的文件。 tar…...

VS2015+opencv 3.4.6开发环境

VS2015+opencv 3.4.6开发环境 一、安装包下载二、安装过程三、VS环境配置四、测试一、安装包下载 这里提供两种下载方法:   1. opencv官网   2. csdn资源下载 二、安装过程 2.1 下载opencv-3.4.6 安装包 2.2 双击开始安装,选择要安装目录,点击Extract。  2.3 等待解…...

[运维|数据库] 将mysql的null.unix_timestamp(now()) * 1000转为PostgreSQL的语法

在 PostgreSQL 中&#xff0c;您可以使用以下方式将 MySQL 中的 UNIX_TIMESTAMP 和 NOW() 函数的组合转换为等效的语法&#xff1a; EXTRACT(EPOCH FROM NOW()) * 1000在这个 PostgreSQL 表达式中&#xff1a; EXTRACT(EPOCH FROM NOW()) 获取当前时间戳的秒数。 2. * 1000 将…...

springboot使用filter增加全局traceId,方便日志查找

一&#xff1a;引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency> 二&#xff1a;编写过滤器&#xff1a; package com.example.demo.filter;import or…...

面经学习三

目录 Java 与 C 的区别 面向对象和面向过程的区别 面向对象特性 Java的基本数据类型 深拷贝和浅拷贝 Java创建对象的几种方式 final, finally, finalize 的区别 Java 与 C 的区别 Java 是纯粹的面向对象语言&#xff0c;所有的对象都继承自 java.lang.Object&#xff0c…...

Open3D 点云配准——可视化匹配点对之间的连线

点云配准 一、算法原理1、概述2、主要函数二、代码实现三、结果展示四、测试数据本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法原理 1、概述 可视化源点云和目标点云中匹配点对之间的连线,这对于点云配准,尤…...

io多路复用之poll的详细执行过程

1.结构体struct pollfd的定义 struct pollfd { int fd; /* 文件描述符 */ short events; /* 想要监视的事件&#xff08;input/output/priority&#xff09; */ short revents; /* 实际发生的事件&#xff08;返回的事件&#xff09; */ }; 2.定义po…...

网络安全深入学习第四课——热门框架漏洞(RCE— Log4j2远程代码执行)

文章目录 一、log4j2二、背景三、影响版本四、漏洞原理五、LDAP和JNDI是什么六、漏洞手工复现1、利用DNSlog来测试漏洞是否存在2、加载恶意文件Exploit.java&#xff0c;将其编译成class文件3、开启web服务4、在恶意文件Exploit.class所在的目录开启LDAP服务5、监听反弹shell的…...

大数据Flink(八十一):SQL 时区问题

文章目录 SQL 时区问题 ​​​​​​​一、SQL 时区解决的问题...

Input子系统 - Kernel驱动程序 - Android

Input子系统 - Kernel驱动程序 - Android 1、Input子系统相关定义1.1 代码位置1.2 input_dev结构体&#xff1a;表示输入设备1.3 input_handler结构体&#xff1a;struct input_handler - implements one of interfaces for input devices1.4 input_handle结构体&#xff1a;将…...

MySQL里的查看操作

文章目录 查看当前mysql有谁连接查看数据库或者表 查看当前mysql有谁连接 show processlist;查看数据库或者表 列出所有数据库&#xff1a; show databases;查看正在使用的数据库&#xff08;必须大写&#xff09;&#xff1a; SELECT DATABASE();列出数据库中的表&#xf…...

Vim的基础操作

前言 本文将向您介绍关于vim的基础操作 基础操作 在讲配置之前&#xff0c;我们可以新建一个文件 .vimrc&#xff0c;并用vim打开在里面输入set nu 先给界面加上行数&#xff0c;然后shift &#xff1b;输入wq退出 默认打开&#xff1a;命令模式 在命令模式中&#xff1a…...

十天学完基础数据结构-第一天(绪论)

1. 数据结构的研究内容 数据结构的研究主要包括以下核心内容和目标&#xff1a; 存储和组织数据&#xff1a;数据结构研究如何高效地存储和组织数据&#xff0c;以便于访问和操作。这包括了在内存或磁盘上的数据存储方式&#xff0c;如何将数据元素组织成有序或无序的集合&…...

神经网络 03(参数初始化)

一、参数初始化 对于某一个神经元来说&#xff0c;需要初始化的参数有两类&#xff1a;一类是权重W&#xff0c;还有一类是偏置b&#xff0c;偏置b初始化为0即可。而权重W的初始化比较重要&#xff0c;我们着重来介绍常见的初始化方式。 &#xff08;1&#xff09;随机初始化 …...

div设置圆角#前端

要在 div元素上设置圆角&#xff0c;您可以使用 CSS 的 border-radius 属性。 这个属性允许您指定元素的边角为圆角&#xff0c;可以将其应用于一个或多个边角。以下是一些示例代码&#xff1a;1.设置所有四个边角为圆角&#xff1a; div {border-radius: 10px; /* 设置所有四…...

Windows开机密码破解

Windows11以及Windows10(21H2)以上版本 先开机&#xff0c;不进行任何操作&#xff0c;静静的等待登录界面 按住Shift重启 进入“选择一个选项”界面&#xff0c;点击疑难解答 点击高级选项 点击命令提示符 输入两行命令 copy C:\windows\system32\uti1man.exe C: \Window…...

Mobirise for Mac:轻松创建手机网站的手机网站建设软件

如果你是一位设计师或者开发人员&#xff0c;正在寻找一款强大的手机网站建设软件&#xff0c;那么Mobirise for Mac绝对值得你尝试。这个独特的应用程序将帮助你轻松创建优雅而实用的手机网站&#xff0c;而无需编写复杂的代码。 Mobirise for Mac的主要特点包括&#xff1a;…...

[npm] npx 介绍与使用说明

[npm] npx 介绍与使用说明 npm 的由来npx 是什么&#xff1f;npx 特点npx 的特点项目安装包的使用全局安装包的避免指定工具包版本--no-install 参数和--ignore-existing 参数使用不同版本的 node-p 参数-c 参数实战应用 执行 GitHub 源码 npm 的由来 说到 npm 就离不开社区文…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

接口自动化测试:HttpRunner基础

相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具&#xff0c;支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议&#xff0c;涵盖接口测试、性能测试、数字体验监测等测试类型…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

微服务通信安全:深入解析mTLS的原理与实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言&#xff1a;微服务时代的通信安全挑战 随着云原生和微服务架构的普及&#xff0c;服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...