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

news2024/11/15 8:30:32

目录

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.coloradmin.cn/o/1568638.html

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

相关文章

面试算法-140-接雨水

题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1,3,2…

网络编程(TCP、UDP)

文章目录 一、概念1.1 什么是网络编程1.2 网络编程中的基本知识 二、Socket套接字2.1 概念及分类2.2 TCP VS UDP2.3 通信模型2.4 接口方法UDP数据报套接字编程TCP流套接字编程 三、代码示例3.1 注意点3.2 回显服务器基于UDP基于TCP 一、概念 首先介绍了什么是网络编程&#xff…

大模型量化技术-GPTQ

大模型量化技术-GPTQ 2022年,Frantar等人发表了论文 GPTQ:Accurate Post-Training Quantization for Generative Pre-trained Transformers。 这篇论文详细介绍了一种训练后量化算法,适用于所有通用的预训练 Transformer模型,同时只有微小的性能下降。 GPTQ算法需要通过…

Autodesk Maya 2025 Multilanguage (macOS, Linux, Windows) - 三维动画和视觉特效软件

Autodesk Maya 2025 Multilanguage (macOS, Linux, Windows) - 三维动画和视觉特效软件 三维计算机动画、建模、仿真和渲染软件 请访问原文链接&#xff1a;https://sysin.org/blog/autodesk-maya/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&a…

‘cv2’、PIL、torch、torchivision

运行环境安装失败集 1、 ModuleNotFoundError: No module named ‘cv2’No module named ‘cv2’ opencv-python PEP517 ERROR2、ModuleNotFoundError: No module named PIL3、torch、torchvision安装 1、 ModuleNotFoundError: No module named ‘cv2’ No module named ‘cv…

基于SSM的社区疫情防控管理信息系统

目录 背景 技术简介 系统简介 界面预览 背景 随着时代的进步&#xff0c;计算机技术已经全方位地影响了社会的发展。随着居民生活质量的持续上升&#xff0c;人们对社区疫情防控管理信息系统的期望和要求也在同步增长。在社区疫情防控日益受到广泛关注的背景下&#xff0c…

JAVAEE——文件IO

文章目录 文件的概念什么是文件&#xff1f;树型结构组织 和 目录文件路径相对路径绝对路径 文件的分类文件的权限 文件读写IO API字符流操作API 警告字节流操作APIInputStreamOutputStream 文件的概念 什么是文件&#xff1f; 我们先来理解一下什么是文件&#xff0c;那么想…

四川尚熠电子商务有限公司靠谱吗?怎么样?

在当下数字化浪潮中&#xff0c;电子商务行业正以前所未有的速度蓬勃发展。四川尚熠电子商务有限公司&#xff0c;作为专注于抖音电商服务的企业&#xff0c;凭借其敏锐的市场洞察力和创新精神&#xff0c;正成为行业内的佼佼者&#xff0c;为众多品牌打开抖音电商市场的大门。…

[技术闲聊]我对电路设计的理解(三)

终于可以独立做项目了&#xff0c;是不是很激动&#xff0c;是不是为自己骄傲和自豪&#xff0c;应该的&#xff0c;奋斗那么久不就是为了站在山巅看看四周的风景嘛&#xff01; 虽说山外还有山&#xff0c;但是此刻就在脚下的山巅上&#xff0c;怡然自得都是不过分的&#xff…

YOLOv8改进 | 低照度检测 | 2024最新改进CPA-Enhancer链式思考网络(适用低照度、图像去雾、雨天、雪天)

一、本文介绍 本文给大家带来的2024.3月份最新改进机制,由CPA-Enhancer: Chain-of-Thought Prompted Adaptive Enhancer for Object Detection under Unknown Degradations论文提出的CPA-Enhancer链式思考网络,CPA-Enhancer通过引入链式思考提示机制,实现了对未知退化条件下…

《内心强大比什么都重要》 - 三余书屋 3ysw.net

内心强大比什么都重要 今天我和大家一起分享一本好书&#xff0c;艾米莫林的《内心强大比什么都重要》。这本书中描述了人们如何控制情绪、想法和行动&#xff0c;让自己的内心更强大。书中也列举了一些有用的建议、积极向上的例子和实际解决方法&#xff0c;来帮助读者们克服…

Python搭建编程环境-安装Python3解释器

✅作者简介&#xff1a;CSDN内容合伙人、新星计划第三季Python赛道Top1&#x1f3c5; &#x1f525;本文已收录于Python系列专栏&#xff1a;零基础学Python &#x1f4ac;订阅专栏后可私信博主进入Python学习交流群&#xff0c;进群可领取Python视频教程以及Python相关电子书…

Linux是什么,该如何学习

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Linux &#xff1a;从菜鸟到飞鸟的逆袭》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Linux的起源与发展 2、Linux在现代计算机领域…

Java源值1.5已过时,将在未来所有发行版中删除

1、背景 确认java项目没问题&#xff0c;但是启动的时候&#xff0c;却报错&#xff1a;java: -source 1.5 中不支持 diamond 运算符 2、解决 2.1 2.2 2.3 2.4 2.5

阿里云PAI-EAS试用-ComfyUI

试用信息 试用地址 PAI-EAS试用 提供资源 其中A10服务器在10元每小时左右&#xff0c;意味着我们可以使用的试用时间在40个小时以上。每天玩4小时&#xff0c;也可以玩10天了&#xff0c;练习完全够用。 具体过程 官方给了一个简单的指导文档&#xff0c;包括领用资源、部…

1688API接口|获取商品详情信息商品列表商品采集API图搜商品API

API调用公共参数 名称类型必须描述keyString是调用key&#xff08;注册账号获取API&secret&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,item_get,item_search_shop等]cacheString否[yes,no]默认…

vulhub中Apache Solr RemoteStreaming 文件读取与SSRF漏洞复现

Apache Solr 是一个开源的搜索服务器。在Apache Solr未开启认证的情况下&#xff0c;攻击者可直接构造特定请求开启特定配置&#xff0c;并最终造成SSRF或任意文件读取。 访问http://your-ip:8983即可查看Apache Solr后台 1.访问http://your-ip:8983/solr/admin/cores?indexI…

Windows通过git配置github代码仓库全流程

git git是代码的版本控制工具 git安装和github注册 这个默认弄过了 通过git和github之间的SSH配置 在github上面新建仓库&#xff0c;做好配置 git绑定GitHub账号 先cd到上传的文件所在的目录 git config --global user.name "你的github用户名"git config -…

Linux 文件相关命令

一、查看文件命令 1&#xff09;浏览文件less 默认查看文件的前 10 行。 less /etc/services ##功能说明&#xff1a; #1.默认打开首屏内容 #2.按【回车】按行访问 #3.按【空格】按屏访问 #4.【从上向下】搜索用/111,搜索包含111的内容&#xff0c;此时按n继续向下搜&#x…

Hadoop: word count,并将结果写入到MySQL

一、依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0…