《数据结构学习笔记---第十篇》--- 堆堆排序(超详细图解)

目录

1.堆是什么?

2.问题引入:当我们插入一个新的元素时,那么他还是堆吗。

3.堆的元素插入

4.问题引入:当我们删除一个堆顶元素时,我们又该如何调整呢?

5.堆顶元素删除

6.如何建堆?

6.1向上调整建堆:

6.2向下调整建堆:

6.3 两者区别:

7.堆排序的实现:


1.堆是什么?

  堆其实从逻辑上看是一棵完全二叉树物理结构上来看就是一个顺序的数组。满足:任何一个非叶节点的值都不大于(或不小于)其左右孩子结点的值。若父亲大,孩子小叫做大根堆,若父亲小,孩子大叫做小根堆。

堆的性质:

  • 堆中某个节点的值总是不大于或不小于其父节点的值;
  • 堆总是一棵完全二叉树。

 从这个树中我们可以看到,下标为奇数刚好为左孩子,下标为偶数刚好为右孩子。

由此我们可以得到孩子与父亲的关系

leftchild=parent*2+1;

rightchild=parent*2+2;

parent=(child-1)/2;

2.问题引入:当我们插入一个新的元素时,那么他还是堆吗。

  如果我们原来有一个堆,但我们又插入了新的数据,那么此时我们就需要进行向上调整,他是个大根堆,按照我们的顺序可以将他重新调整为大根堆。那么我们最容易误解的就是如果原本是个小根堆的话是不是就要向下调整呢?实际情况小根堆的新元素插入也是向上调整的,只不过就是元素的对比条件与大根堆不同,但代码逻辑都是向上比较的,都是一个爬升的过程。

 代码展示

void AdjustUp(HPDataType* 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;}}
}

我们知道了堆增加元素后如何使他变成新的堆,那么我们就可以进行堆的插入操作了。

3.堆的元素插入

代码展示

void HeapPush(HP* hp, HPDataType x)
{assert(hp);if (hp->size == hp->capacity){int newcapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;//申请扩容HPDataType* tmp = (HPDataType*)realloc(hp->a, sizeof(HPDataType) * newcapacity);//千万别忘了怎么扩容的if (tmp == NULL){perror("realloc fail");exit(-1);}hp->capacity = newcapacity;hp->a = tmp;}hp->a[hp->size] = x;hp->size++;AdjustUp(hp->a , hp->size - 1);
}

考虑到我们的堆存储结构实际上是顺序结构,所以当我们插入元素可能会用到异地扩容。

4.问题引入:当我们删除一个堆顶元素时,我们又该如何调整呢?

如图,为了方便操作,我们把堆底的元素和堆顶的元素进行了调换,这样我们可以保证他的逻辑结构还是一颗完全二叉树,方便我们进行调整操作。

此时,我们进行的是向下调整算法,我们可以观察出我们向下调整算法的前提:左右子树必须是一个堆,才能调整。

代码展示:

void AdjustDown(HPDataType* a, int n, int parent)
{int child = parent * 2 + 1;while (child<n)//要分两个独立的判断 1.先判断孩子的大小,拿出一个最大的。2.然后拿出的最大的与根比较,最终决定是否交换位置{if (child+1 < n && a[child+1]> a[child]){child++;//指向大的孩子}if (a[child] > a[parent]){Swap(&a[parent], &a[child]);parent = child;child = parent * 2 + 1;}else{break;}}}

我们知道了堆删除元素后如何使他变成新的堆,那么我们就可以进行堆的删除操作了。

5.堆顶元素删除

代码展示:

void HeapPop(HP* hp)
{assert(hp);assert(hp->size>0);Swap(&hp->a[0] ,&hp->a[hp->size-1]);//这里忘记减一了hp->size--;AdjustDown(hp->a, hp->size, 0);}

6.如何建堆?

第一种方法就是,我们可以不断地插入新元素,然后再进行向上调整操作。实质上就是第二种方法中的向上调整建堆。

图解:

代码展示:

void HeapCreate(HP* hp, HPDataType* a, int n)
{assert(hp);HeapInit(hp);for (int i = 0; i < n; ++i){HeapPush(hp, a[i]);}
}

第二种方法是我们先开辟出一个新的数组,就是堆已有的数组进行调整,但是到底是向上调整还是向下调整我们又分为了两种情况:

6.1向上调整建堆:

图解建堆

 代码展示:

void HeapCreate(HP* hp, HPDataType* a, int n)
{assert(hp);hp->a = (HPDataType*)malloc(sizeof(HPDataType) * n);//千万别忘了怎么扩容的if (hp->a == NULL){perror("malloc fail");exit(-1);}memcpy(hp->a, a, sizeof(HPDataType) * n);hp->capacity = hp->size = n;for (int i = 1; i<n ; ++i){AdjustUp(hp->a, i);}
}

6.2向下调整建堆:

图解建堆:

代码展示:

void HeapCreate(HP* hp, HPDataType* a, int n)
{assert(hp);hp->a = (HPDataType*)malloc(sizeof(HPDataType) * n);//千万别忘了怎么扩容的if (hp->a == NULL){perror("malloc fail");exit(-1);}memcpy(hp->a, a, sizeof(HPDataType) * n);hp->capacity = hp->size = n;for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(hp->a, n, i);}
}

6.3 两者区别:

向下调整时:

向上调整时:

因此,当我们想要建堆的时候,我们优先选择向下调整建堆,他的时间代价更小。

问题引入:我们实现堆,是为了排序,那如果我们为了要升序序列,我们应该是怎样建堆?

7.堆排序的实现:

如果我们为了实现升序序列,我们应该建立大堆还是小堆?

应该是建立大堆

图解:

从图上我们可以看出,建立大堆的目的就是把最大的值,给放到数组的后面,也就是挑选出来,最后的数组里就是按升序排列的。当然我们要想实现降序序列,就是需要建立大根堆,将小的数挑选出来。

代码展示:

void HeapSort(int* a, int n)
{for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(a, n, i);}// O(N*logN)int end = n - 1;while (end > 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}
}void Test3()
{int array[] = { 27, 15, 19, 18, 28, 34, 65, 49, 25, 37 };HeapSort(array, sizeof(array) / sizeof(int));for (int i = 0; i < sizeof(array) / sizeof(int); ++i){printf("%d ", array[i]);}printf("\n");}

堆排序的性能分析:

1.空间效率:

仅使用常数个辅助单元,空间复杂度为O(1)。

2.时间效率:

建堆的时间O(n),之后又向下调整操作n-1次,而完全二叉树的高度为 logN,最后平均时间复杂度为 O(N*logN)。

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

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

相关文章

图解PyTorch中的torch.gather函数和 scatter 函数

前言 torch.gather在目前基于 transformer or query based 的目标检测中&#xff0c;在最后获取目标结果时&#xff0c;经常用到。 这里记录下用法&#xff0c;防止之后又忘了。 介绍 torch.gather 官方文档对torch.gather()的定义非常简洁 定义&#xff1a;从原tensor中获…

ctf_show笔记篇(web入门---SSRF)

ssrf简介 ssrf产生原理&#xff1a; 服务端存在网络请求功能/函数&#xff0c;例如&#xff1a;file_get_contens()这一类类似于curl这种函数传入的参数用户是可控的没有对用户输入做过滤导致的ssrf漏洞 ssrf利用: 用于探测内网服务以及端口探针存活主机以及开放服务探针是否存…

深入浅出 -- 系统架构之分布式架构

​​​​​​分布式架构&#xff1a; 根据业务功能对系统做拆分&#xff0c;每个业务功能模块作为独立项目开发&#xff0c;称为一个服务。 当垂直应用越来越多时&#xff0c;应用之间的交互不可避免&#xff0c;可将共用的基础服务或核心模块抽取出来作为独立服务&#xff0c…

ubuntu无法粘贴复制windows中的内容,分辨率无法自适应电脑自带系统

1、直接在命令行执行以下命令 sudo apt-get autoremove open-vm-tools //卸载已有的工具 sudo apt-get install open-vm-tools //安装工具open-vm-tools sudo apt-get install open-vm-tools-desktop //安装open-vm-tools-desktop 2、重启Ubuntu系统即可 3.如果上述…

mbti,ESTP型人格的心理问题分析

什么是ESTP型人格 ESTP分别代表外向&#xff0c;实感&#xff0c;理智&#xff0c;依赖&#xff0c;而ESTP型人格则是一种性格上十分激进&#xff0c;喜欢冒险&#xff0c;并且总是因为情绪起伏过大&#xff0c;而一下子做出应激行为的相对冒险的人格。具有ESTP型人格的人一般…

Hadoop-HDFS

资料来源&#xff1a;尚硅谷-Hadoop 一、HDFS 概述 1.1 HDFS 产出背景及定义 1.1.1 HDFS 产生背景 随着数据量越来越大&#xff0c;在一个服务器上存不下所有的数据&#xff0c;那么就分配到更多的服务器管理的磁盘中&#xff0c;但是不方便管理和维护&#xff0c;迫切需要…

Web实例_报表开发01-基于HTML进行报表呈现

Web实例_报表开发01-基于HTML进行报表呈现 报表开发是一种在利用了软件的基础上, 针对不同类型的报表, 进行开放的工作。 而以报表的方式, 将相关的内容、数值呈现出来的话, 则会起到更好的概况作用。 再加上, 报表开发工作是依托于计算机来完成的, 因此在效率、完整性等方面…

Learning To Count Everything

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;学习数一切东西1、研究背景2、提出方法3、模块详细3.1、多尺度特征提取模块3.2、密度预测模块 4、损失函数5、性能对比6、贡献 二…

《机器学习算法面试宝典》正式发布!

大家好&#xff0c;历时半年的梳理和修改&#xff0c;《机器学习算法面试宝典》&#xff08;以下简称《算法面试宝典》&#xff09;终于可以跟大家见面了。 近年来&#xff0c;很多理科专业学生也纷纷转入算法赛道&#xff0c;特别是最近 ChatGPT 的爆火&#xff0c;推动了AI …

加密软件VMProtect教程:使用脚本-功能

VMProtect是新一代软件保护实用程序。VMProtect支持德尔菲、Borland C Builder、Visual C/C、Visual Basic&#xff08;本机&#xff09;、Virtual Pascal和XCode编译器。 同时&#xff0c;VMProtect有一个内置的反汇编程序&#xff0c;可以与Windows和Mac OS X可执行文件一起…

http模块 设置资源类型(mime类型)

虽然浏览器自带websocket功能它会根据响应回来的内容自动去判断资源类型&#xff0c;但是我们加上了mime类型判断代码会更加规范些 一、mime类型概念&#xff1a; 媒体类型是一种标准&#xff0c;它用来表示文档。文件、字节流的性质和格式。HTTP服务可以设置响应头Content-T…

「精细化管理」某物业集团精细化管理咨询项目纪实

实现工作例行化、定时化、程序化与可视化企业重视绩效考核&#xff0c;却总感觉考核不到点上&#xff1b;企业重视规划职责&#xff0c;却总感觉部门间职责不清&#xff1b;企业重视激励&#xff0c;却总感觉难以真正激励员工。到底是哪里出了问题&#xff1f;华恒智信指出&…