数据结构:堆与堆排序

目录

堆的定义:

堆的实现:

堆的元素插入:

堆元素删除:

堆初始化与销毁:

堆排序:


堆的定义:

堆是一种完全二叉树,完全二叉树定义如下:

一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。

    堆分为两类:小堆和大堆。小堆是指堆中任意一个节点都值小于它的孩子节点值。同理,大推指任意一个节点的值都大于它孩子节点的值。

堆的结构:

事实上,堆在逻辑结构上可以看作是一种完全二叉树,但在内存中是以数组的方式存储的。堆内节点的下标可以在计算机内如此计算出来:

左孩子节点的下标 = 父节点的下标*2+1

右孩子节点的下标 = 父节点的下标*2+2

父节点的下标 = (子节点下标 - 1)/2

我们可以很容易看出来,堆数据的插入在逻辑上是一层一层地插入,这一层存满后再到下一层存储。

堆的实现:
Typedef 数据类型 DataType
struct heap {  DataType* t;//堆数组内数据类型,指向第一个元素的指针int size;  //堆内元素个数int capacity;  //堆内元素容量}hp;
堆的元素插入:

  由于堆的结构特性,即小堆的双亲节点比它的子节点都要大,大堆的父节点比他的子节点都要小。因此每在数组后插入一个数据都要将这个数据调整到它应该存储的位置,这种调整在逻辑结构中是从下至上的顺序,因此也称为向上调整。

    每次都与自己的双亲节点对比,在小堆中,如果双亲节点的数据大于插入的新数据,那么两节点作数据交换,依次作交换直到双亲节点数据小于该新插入的数据为止。

    首先我们实现一个向上调整的代码:

void AdjustUp(HpType* a, int child){int parent = (child  - 1)/2;//先计算出当前插入数据节点的父节点下标while(child > 0){ if(a[child] < a[parent]){HpType tmp = a[child];a[child] = a[parent];a[parent] = tmp;     //交换两节点数据parent = child;child  = (parent - 1)/2;  //更新父子节点的值,使其指向下一组父子节点}else{break;} }}

实现完调整堆的代码后,我们可以实现插入数据:

void HeapPush(hp* php,HpDataType x)
{assert(hp);int newCapacity = php->Capacity == 0?4:2*Capacity;HpDataType* tmp = (HpDataType*)realloc(php->a, newCapacity*sizeof(HpDataType);
if(tmp == null) //扩容失败的情况{perror("realloc failed");}php->t[php->size] = x;php->size++;AdjustUp(php->t,php->size - 1];//插入后调整堆
}
堆元素删除:

    堆元素删除是将堆首元素删除的算法。对于堆元素删除,通过上面的逻辑,像数组一样单纯将该数据从数组中移除并将后面的数据向前移动是不可行的,因为会导致堆结构的破坏,父节点和子节点不会形成一致的大小关系,因此我们要实现一个算法实现数据删除后对整个堆进行调整的。

   堆元素删除的算法思想是,将堆末尾元素与首元素进行交换,并将末尾元素删除,此时要删除的元素已经被移出。然后将变换后堆的首元素进行向下调整,调整到它应在的位置。

void AdjustDown(HpDataType* a, int parent,int size)
{int child = parent*2 + 1;while(child < size){if( child+1 < size && a[parent*2 + 1] > a[parent*2 + 2]){child++;}if(a[parent] > a[child]){ swap(&a[parent],&a[child];parent = child;child  = parent*2 + 1;}else{break;}}}

实现完向下调整算法后即可实现堆删除顶部元素算法:

void HeapPop(ph* php){assert(php);assert(!HeapEmpty(php));swap(php->t[0],php->[size-1]); //将首尾元素进行交换php->size--;AdjustDown(ph,php->t[0],php->size); //向下调整元素}
堆初始化与销毁:
void HeapInit(hp* php)
{assert(php);php->t = null;php->size = 0;php->Capacity = 0;
}void HeapDestroy(hp* php){  assert(php);free(php);}
 堆排序:

    堆排序是很重要的一种排序,从堆的增删查改操作衍生而来,由于其较低的时间复杂度运用较为广泛。

    堆排序算法运用到堆的向下调整和,首先传入一个未排序的数组,此时对该数组进行建堆操作。如果我们新建一个堆,再把数组内数据传入堆内会浪费较大的空间。有没有方法可以对数组本身进行建堆操作呢?

    我们可以想象,对数组本身进行建堆操作,把数组看作是从第一个数开始一直插入n - 1个数形成。那么我们就可以将后面n - 1个数进行插入然后向上调整建堆。

void HeapSort(int* a,n){for(int i = 1;i < n;i++){ AdjustUp(a,i);}}

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

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

相关文章

linux性能优化-磁盘I_O优化

1.文件系统 1.1.文件系统的工作原理 文件系统是在磁盘的基础上&#xff0c;提供了一个用来管理文件的树状结构。 接下来我们就看看Linux 文件系统的工作原理。 1.1.1索引节点和目录项 在 Linux 中一切皆文件 ,文件系统,本身是对存储设备上的文件&#xff0c;进行组织管理的…

go和swoole性能比较

开发效率 Go语言是本质上是静态语言&#xff0c;开发效率稍差&#xff0c;但性能更强&#xff0c;更适合底层软件的开发 Swoole使用PHP语言&#xff0c;动态脚本语言&#xff0c;开发效率最佳&#xff0c;更适合应用软件的开发 IO模型 go语言使用单线程eventloop处理IO事件&…

阿里云优惠券领取入口、使用方法和限制条件,2024最新

阿里云优惠代金券领取入口&#xff0c;阿里云服务器优惠代金券、域名代金券&#xff0c;在领券中心可以领取当前最新可用的满减代金券&#xff0c;阿里云百科aliyunbaike.com分享阿里云服务器代金券、领券中心、域名代金券领取、代金券查询及使用方法&#xff1a; 阿里云优惠券…

sqlmap使用教程(2)-连接目标

目录 连接目标 1.1 设置认证信息 1.2 配置代理 1.3 Tor匿名网络 1.4 检测WAF/IPS 1.5 调整连接选项 1.6 处理连接错误 连接目标 场景1&#xff1a;通过代理网络上网&#xff0c;需要进行相应配置才可以成功访问目标主机 场景2&#xff1a;目标网站需要进行身份认证后才…

72.批量执行Redis命令的4种方式!

文章目录 前言一、Redis命令执行过程二、原生批量命令三、pipeline(管道)四、Lua脚本五、Redis事务六、Redis Cluster模式下该如何正确使用批量命令操作&#xff1f; 前言 在我们的印象中Redis命令好像都是一个个单条进行执行的&#xff0c;但实际上我们是可以批量执行Redis命…

LLM:Sinusoidal-正余弦位置编码

1&#xff1a;什么是大模型的外推性&#xff1f; 外推性是指大模型在训练时和预测时的输入长度不一致&#xff0c;导致模型的泛化能力下降的问题。例如&#xff0c;如果一个模型在训练时只使用了512个 token 的文本&#xff0c;那么在预测时如果输入超过512个 token&#xff0…

FPGA引脚物理电平(内部资源,Select IO)-认知2

引脚电平 The SelectIO pins can be configured to various I/O standards, both single-ended and differential. • Single-ended I/O standards (e.g., LVCMOS, LVTTL, HSTL, PCI, and SSTL) • Differential I/O standards (e.g., LVDS, Mini_LVDS, RSDS, PPDS, BLVDS, and…

源聚达科技:抖音店铺出单需要多久

随着互联网的发展&#xff0c;电商平台已经成为了人们购物的主要渠道之一。其中&#xff0c;抖音作为短视频平台的佼佼者&#xff0c;也吸引了大量的商家入驻。然而&#xff0c;对于刚刚入驻抖音店铺的商家来说&#xff0c;他们最关心的问题之一就是&#xff1a;抖音店铺出单需…

接口测试 03 -- 接口自动化思维 Requests库应用

1. 接口自动化思维梳理 1.1接口自动化的优点 接口测试自动化&#xff0c;简单来讲就是功能测试用例脚本化然后执行脚本&#xff0c;产生一份可视化测试报告。不管什么样的测试方式&#xff0c;都是为了验证功能与发现 BUG。那为什么要做接口测试自动化呢&#xff1f;一句话概括…

matlab appdesigner系列-常用16-状态按钮

状态按钮&#xff0c;有两个状态&#xff0c;按下状态&#xff0c;返回值为1或true&#xff1b;未按下状态&#xff0c;返回值为0或false 示例&#xff1a;设置一状态按钮&#xff0c;用文本记录其状态 操作步骤&#xff1a; 1&#xff09;将状态按钮、文本区域拖拽到画布上…

mysql进阶-执行计划

目录 1. 概念 2. 使用 3. 具体相关字段含义 3.1 id 3.2 select_type 3.3 table 3.4 partition 3.5 type 3.6 possible_key 3.7 key 3.8 key_len 3.9 ref 3.10 row 3.11 filtered 3.12 extra 1. 概念 一条语句通过优化器之后&#xff0c;会生成具体的执行计划用…

小程序使用echarts图表-雷达图

本文介绍下小程序中如何使用echarts 如果是通过npm安装&#xff0c;这样是全部安装的&#xff0c;体积有点大 我这边是使用echarts中的一个组件来实现的&#xff0c;下边是具体流程&#xff0c;实际效果是没有外边的红色边框的&#xff0c;加红色边框的效果是这篇说明 1.echa…