数据结构:堆与堆排序

news2024/9/22 20:40:52

目录

堆的定义:

堆的实现:

堆的元素插入:

堆元素删除:

堆初始化与销毁:

堆排序:


堆的定义:

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

一棵深度为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.coloradmin.cn/o/1404493.html

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

相关文章

cpu温度监测工具 -- Turbo Boost Switcher Pro

Turbo Boost Switcher Pro是一款专为Mac电脑设计的CPU性能管理软件&#xff0c;它的技术背后是Intel Turbo Boost。Turbo Boost技术是一项能够自动加速处理器主频的技术&#xff0c;为Mac电脑提供更强大的计算能力。然而&#xff0c;这项技术在使用过程中会产生更多热量&#x…

云风网(www.niech.cn)个人网站搭建(二)服务器域名配置

这里直接采用宝塔服务器运维管理面板来进行配置&#xff0c;简单无脑 宝塔 Linux面板8.0.5安装脚本 //Centos安装脚本 yum install -y wget && wget -O install.sh https://download.bt.cn/install/install_6.0.sh && sh install.sh ed8484bec //Ubuntu/Deepi…

JVM系列-4.类加载器

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理&#x1f525;如果感觉博主的文…

java数据结构与算法刷题-----LeetCode645. 错误的集合(位运算解法需要重点掌握)

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 法一&#xff1a;桶排序思想法二&#xff1a;位运算 法一&#x…

imu_utils安装及标定教程

本文使用香港科技大学的imu_utils方差工具标定&#xff0c;首先将INDEMIND双目惯性模组静止放置三个小时。然后采集IMU数据&#xff0c;生成Allan方差数据&#xff0c;由图分析得到加速度和角速度的高斯白噪声和随机游走Bias误差。 系统配置 系统版本ubuntu18.04OpenCV3.4.13…

C/C++读写文件和stringstream类

目录 C处理文件打开文件两种函数的区别 读文件两种函数区别其它读操作的函数fgetc&#xff1a;从文件中读取一个字符fgets&#xff1a;从文件中读取一个字符串fscanf&#xff1a;按格式从文件中读取指定内容&#xff0c;与scanf函数类似 写文件其它的常用写操作函数fputc&#…

【LeetCode-135】分发糖果(贪心)

LeetCode135.分发糖果 题目描述 老师想给孩子们分发糖果&#xff0c;有 N 个孩子站成了一条直线&#xff0c;老师会根据每个孩子的表现&#xff0c;预先给他们评分。 你需要按照以下要求&#xff0c;帮助老师给这些孩子分发糖果&#xff1a; 每个孩子至少分配到 1 个糖果。…

js中找出两个数组中不同的元素

文章目录 一、题目二、方法2.1、方法一2.2、方法二2.3、方法三 三、最后 一、题目 两个数组 var A [1, 5, 6]; var B [2, 6, 7]&#xff0c;实现一个方法&#xff0c;找出仅存在于A 或者仅存在于B中的所有数字 二、方法 2.1、方法一 const filterArr (arr1, arr2) > …

5大免费代理IP合集,你的代理IP该换啦!

一连代理 代理IP提供平台&#xff0c;代理IP覆盖HTTP/HTTPS/SOCKS5协议&#xff0c;涵盖直连和隧道代理。一键操作可以随机更换IP&#xff0c;实现高效稳定的网络代理。支持在PC、iOS和安卓等平台上使用。当前免费试用选项&#xff0c;让用户能够在使用之前先了解服务的性能和效…

归并排序模板

模板在文末&#xff0c;以下步骤方便理解记忆。 先贴一张快速排序模板步骤&#xff0c;用于对比记忆 归并排序步骤&#xff1a; &#xff08;0&#xff09;如果数组左边界L ≥ 数组右边界&#xff0c;则不需要排序&#xff0c;直接return。 &#xff08;1&#xff09;直接取…

力扣第92题——反转链表 II(C语言题解)

题目描述 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#xff1…

成绩等级分数段查询(python条件分支语句match...case...)

根据有效分数序列及等级差值&#xff0c;计算并打印等级相应分数区间。 (笔记模板由python脚本于2024年01月20日 23:57:32创建&#xff0c;本篇笔记适合会条件分支语句的初学者的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&…

python:socket基础操作(2)-《udp发送信息》

基础发送udp信息 1.导入socket模块 2.使用udp模块 3.发送内容 4.关闭套接字 很简单的4步就可以实现udp的消息发送 import socket # 导入模块udp_socket socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 使用ipv4 udp协议udp_socket.sendto(b"hello world",(&…

翻毛皮鞋脏了不会清洗怎么办?资深劳保鞋厂家来教你

劳保鞋皮面材质中除了常见的牛皮材质&#xff0c;翻毛皮也是频繁使用的材料&#xff0c;材质不同&#xff0c;在养护上也有区别&#xff0c;今天百华小编来和大家聊聊翻毛皮材质的鞋子清洁方法。 翻毛皮鞋清洗前的准备工作 1.除灰&#xff1a;对于表面灰尘&#xff0c;可以使用…

C语言第六弹---分支语句(下)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 分支语句 1、 逻辑操作符&#xff1a;&& , || , &#xff01;4.1、 逻辑取反运算符 &#xff01;4.2、 与运算符4.3、 或运算符4.4、 练习&#xff1a;闰…

磁悬浮人工心脏的不良事件分析:美国FDA数据库的启示

引言&#xff1a; 左心室辅助装置&#xff08;LVAD&#xff09;是治疗末期难治性心力衰竭&#xff08;HF&#xff09;患者的有效手段。磁悬浮人工心脏HeartMate-3&#xff08;磁悬浮人工心脏&#xff09;作为第三代LVAD&#xff0c;自2017年获得美国食品药品监督管理局&#x…

pygame入门学习(四)位图的使用

大家好&#xff01;我是码银&#x1f970; 欢迎关注&#x1f970;&#xff1a; CSDN&#xff1a;码银 公众号&#xff1a;码银学编程 载入图片 pygame.image.load( )&#xff0c;Pygame 可以通过pygame.image.load( )函数处理位图文件。 大致可以支持以下文件&#xff1a;JPG…

怎么给wordpress网站底部页脚添加备案号和链接?

以前“WordPress后台 >> 常规”最底部是有一个ICP备案号的&#xff0c;我们只需要填写备案号并保存更改即可让WordPress自带主题底部显示ICP备案号&#xff0c;但是现在新版本的WordPress已经没有了这个ICP备案号选项&#xff0c;而且也无法直接添加公安联网备案号&#…

前端基于XLSX实现数据导出到Excel表格,以及提示“文件已经被损坏,无法打开”的解决方法

文章目录 一、vue实现导出excel1、前端实现1、安装xlsx依赖2、引入3、方法4、使用4.1、将一个二维数组转成sheet4.2、将一个对象数组转成sheet4.3、合并单元格4.4、一次导出多个sheet 5、支持的文件格式 2、后端实现 二、导出文件损坏1、前端请求导出接口&#xff0c;增加返回类…

对称二叉树,力扣

题目地址&#xff1a; 101. 对称二叉树 - 力扣&#xff08;LeetCode&#xff09; 难度&#xff1a;简单 今天刷对称二叉树&#xff0c;大家有兴趣可以点上面链接&#xff0c;看看题目要求&#xff0c;试着做一下。 题目&#xff1a; 给你一个二叉树的根节点 root &#xff0c;…