【数据结构与算法】二叉树——堆的增删查改

简介: 【数据结构与算法】二叉树——堆的增删查改
🌹作者:云小逸
📝个人主页: 云小扬的主页
📝码云: 云小扬 (YunXiaoYang003) - Gitee.com
🤟motto:要敢于一个人默默的面对自己, ==强大自己才是核心==。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前,其次就是现在!学会自己和解,与过去和解,努力爱自己。==希望春天来之前,我们一起面朝大海,春暖花开==!🤟
👏专栏:C语言初阶👏专栏:C语言进阶👏专栏:数据结构和算法👏
👏专栏:C++初阶---👏专栏:C++进阶--👏专栏:Linux学习👏

@TOC

前言

前面我们已经说了关于二叉树的相关概念和二叉树的前、中、后序遍历,今天我们就来学习一下,二叉树的一种形式:堆。
——————————————————————————————
首先先写上几句话:献给坚持创作的我和点开这篇文章希望进步的你

a.这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。
b.什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。
c.大部分人在二三十岁上就死去了,因为过了这个年龄,他们只是自己的影子,此后的余生则是在模仿自己中度过。日复一日,更机械,更装腔作势地重复他们在有生之年的所作所为,所思所想,所爱所恨。


1.堆的基本概念和结构:

a.堆的概念

二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树)。二叉堆有两种:最大堆和最小堆。
最大堆:父结点的键值总是大于或等于任何一个子节点的键值;
最小堆:父结点的键值总是小于或等于任何一个子节点的键值。

b.堆的性质

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

c.堆的结构

物理上:一维数组
逻辑上:完全二叉树
小根堆

2.堆的操作

注:插入删除不可以改变堆的性质,即大堆或小堆,本篇代码是以小堆为例子!!!

(1)堆的建立

typedef int HPDataType;
typedef struct Heap
{
    HPDataType* a;
    size_t size;
    size_t capacity;
}HP;

(2)堆的初始化

void HeapInit(HP* php)
{
    assert(php);
    php->a = NULL;
    php->capacity = php->size = 0;
}

(3)堆的插入

思想:向上调整算法

逻辑上:

在这里插入图片描述

物理上:

在这里插入图片描述

交换函数:

void HeapSwap(HPDataType* pa,HPDataType* pb)
{
    HPDataType temp = *pa;
    *pa = *pb;
    *pb = temp;
}

向上调整算法函数

void AdjustUp(HPDataType* a, size_t child)
{
    size_t parent = (child - 1) / 2;
    while (child > 0)
    {
        if (a[child] < a[parent])
        {
            HeapSwap(&a[child], &a[parent]);
            child = parent;
            parent = (child - 1) / 2;
        }
        else
            break;
    }
}

插入函数

void HeapPush(HP* php, HPDataType x)
{
    assert(php);//插入之前要想考虑是否要扩容!!!
    if (php->size == php->capacity)
    {
        size_t newnode = php->capacity == 0 ? 4 : php->capacity * 2;
        HPDataType* temp = realloc(php->capacity, sizeof(HPDataType) * newnode);
        if (temp == NULL)
        {
            printf("realloc failed!\n");
            exit(-1);
        }
        php->a = temp;
        php->capacity = newnode;
    }
    php->a[php->size] = x;
    php->size++;
    AdjustUp(php->a, php->size - 1);
}

在这里插入图片描述

(4)堆的删除

思想:向下调整法

在这里插入图片描述

向下调整函数:

void AdjustDown(HPDataType* a, size_t size, size_t root)
{
    size_t parent = root;
    size_t child = parent * 2 + 1;
    while (child < size)
    {
        if (child<size && a[child]>a[child + 1])
        {
            child++;
        }
        if (a[parent] > a[child])
        {
            HeapSwap(&a[parent], &a[child]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
            break;
    }
}

删除函数

void HeapPop(HP* php)
{
    assert(php);
    assert(php->size);
    HeapSwap(&php->a[0], &php->a[php->size - 1]);
    php->size--;
    AdjustDown(php->a, php->size, 0);
}

在这里插入图片描述

(5)判断堆是否为空

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

(6)求堆的长度

size_t HeapSize(HP* php)
{
    assert(php);
    return php->size;
}

在这里插入图片描述

(7)返回堆顶的值

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

在这里插入图片描述

(8)销毁堆

void HeapDestroy(HP* php)
{
    assert(php);
    php->a = NULL;
    php->size = php->capacity = 0;
    free(php);
}

(9)遍历堆

void HeapPrint(HP* php)
{
    assert(php);
    size_t i = 0;
    for (i = 0; i < php->size; i++)
    {
        printf("%d  ", php->a[0]);
    }
    printf("\n");
}

完整源码:

Heap.h文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int HPDataType;
typedef struct Heap
{
    HPDataType* a;
    size_t size;
    size_t capacity;
}HP;
void HeapInit(HP* php);
void HeapInit(HP* php);
void HeapSwap(HPDataType* pa, HPDataType* pb);
void AdjustUp(HPDataType* a, size_t child);
void HeapPush(HP* php, HPDataType x);
void AdjustDown(HPDataType* a, size_t size, size_t root);
void HeapPop(HP* php);
bool HeapEmpty(HP* php);
size_t HeapSize(HP* php);
HPDataType HeapTop(HP* php);
void HeapDestroy(HP* php);
void HeapPrint(HP* php);

Heap.c文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"
void HeapInit(HP* php)
{
    assert(php);
    php->a = NULL;
    php->capacity = php->size = 0;
}
void HeapSwap(HPDataType* pa,HPDataType* pb)
{
    HPDataType temp = *pa;
    *pa = *pb;
    *pb = temp;
}
void AdjustUp(HPDataType* a, size_t child)
{
    size_t parent = (child - 1) / 2;
    while (child > 0)
    {
        if (a[child] < a[parent])
        {
            HeapSwap(&a[child], &a[parent]);
            child = parent;
            parent = (child - 1) / 2;
        }
        else
            break;
    }
}
void HeapPush(HP* php, HPDataType x)
{
    assert(php);//插入之前要想考虑是否要扩容!!!
    if (php->size == php->capacity)
    {
        size_t newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
        HPDataType* temp = realloc(php->a, sizeof(HPDataType) * newcapacity);
        if (temp == NULL)
        {
            printf("realloc failed!\n");
            exit(-1);
        }
        php->a = temp;
        php->capacity = newcapacity;
    }
    php->a[php->size] = x;
    php->size++;
    AdjustUp(php->a, php->size - 1);
}
void AdjustDown(HPDataType* a, size_t size, size_t root)
{
    size_t parent = root;
    size_t child = parent * 2 + 1;
    while (child < size)
    {
        if (child<size && a[child]>a[child + 1])
        {
            child++;
        }
        if (a[parent] > a[child])
        {
            HeapSwap(&a[parent], &a[child]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
            break;
    }
}
void HeapPop(HP* php)
{
    assert(php);
    assert(php->size);
    HeapSwap(&php->a[0], &php->a[php->size - 1]);
    php->size--;
    AdjustDown(php->a, php->size, 0);
}
bool HeapEmpty(HP* php)
{
    assert(php);
    return php->size==0;
}
size_t HeapSize(HP* php)
{
    assert(php);
    return php->size;
}
HPDataType HeapTop(HP* php)
{
    assert(php);
    return php->a[0];
}
void HeapDestroy(HP* php)
{
    assert(php);
    php->a = NULL;
    php->size = php->capacity = 0;
    free(php);
}
void HeapPrint(HP* php)
{
    assert(php);
    size_t i = 0;
    for (i = 0; i < php->size; i++)
    {
        printf("%d  ", php->a[i]);
    }
    printf("\n");
}

test.c文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"
int main(void)
{
    HP hp;
    HeapInit(&hp);
    HeapPush(&hp, 1);
    HeapPrint(&hp);
    HeapPush(&hp, 5);
    HeapPrint(&hp);
    HeapPrint(&hp);
    HeapPush(&hp, 0);
    HeapPrint(&hp);
    HeapPush(&hp, 8);
    HeapPrint(&hp);
    HeapPush(&hp, 3);
    HeapPrint(&hp);
    HeapPush(&hp, 9);
    HeapPrint(&hp);
    HeapPop(&hp);
    HeapPrint(&hp);
    HeapPop(&hp);
    HeapPrint(&hp);
    HeapPop(&hp);
    HeapPrint(&hp);
    printf("%d\n", HeapSize(&hp));
    printf("%d", HeapTop(&hp));
    return 0;
    HeapDestroy(&hp);
}

运行结果截图:

在这里插入图片描述

最后

十分感谢你可以耐着性子把它读完和我可以坚持写到这里,送几句话,对你,也对我:

  1. 我的人生是一栋只能建造一次的楼房,我必须让它精确无比,不能有一厘米差池——所以,我太紧张,害怕行差步错。

2.我不想要那种一眼就可以看到死的人生,那种 “我们到底是活了365天,还是活了一天却重复了364遍” 的悲哀,我实在无法想象日复一日的重复一天的人生还有什么意义,我才20岁,人生难道就此再无波澜和际遇?
3.这对我来说依旧可怕,我害怕后果,害怕行差步错,害怕放弃了所有 却依旧失去了她。
4.只问自由,只问盛放,只问深情,只问初心,只问勇敢,无问西东
5.少发脾气。收敛脾气,内心才有元气。不同层次无需讲道理;不同位置无需争辩对错;三观不合无需探讨私事。
6.在感情中及时止损,该说拜拜的人不回头挽留。
7.不刻意满足别人的期待而活着。敢做真实的自己,才有人爱上真实的你。按照自己喜欢的方式去生活,越多对的人会向你靠近。

最后如果觉得我写的还不错,请不要忘记==点赞==✌,==收藏==✌,加==关注==✌哦(。・ω・。)

愿我们一起加油,奔向更美好的未来,愿我们从懵懵懂懂的一枚==菜鸟==逐渐成为==大佬==。加油,为自己点赞!

目录
相关文章
|
8天前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
29 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
10天前
|
存储 JavaScript 前端开发
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
37 1
|
11天前
|
存储 算法 关系型数据库
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
这篇文章主要介绍了多路查找树的基本概念,包括二叉树的局限性、多叉树的优化、B树及其变体(如2-3树、B+树、B*树)的特点和应用,旨在帮助读者理解这些数据结构在文件系统和数据库系统中的重要性和效率。
13 0
数据结构与算法学习二一:多路查找树、二叉树与B树、2-3树、B+树、B*树。(本章为了解基本知识即可,不做代码学习)
|
11天前
|
存储 算法 搜索推荐
数据结构与算法学习十七:顺序储存二叉树、线索化二叉树
这篇文章主要介绍了顺序存储二叉树和线索化二叉树的概念、特点、实现方式以及应用场景。
14 0
数据结构与算法学习十七:顺序储存二叉树、线索化二叉树
|
11天前
|
存储 算法
探索数据结构:分支的世界之二叉树与堆
探索数据结构:分支的世界之二叉树与堆
|
11天前
|
存储 算法
数据结构与算法学习十六:树的知识、二叉树、二叉树的遍历(前序、中序、后序、层次)、二叉树的查找(前序、中序、后序、层次)、二叉树的删除
这篇文章主要介绍了树和二叉树的基础知识,包括树的存储方式、二叉树的定义、遍历方法(前序、中序、后序、层次遍历),以及二叉树的查找和删除操作。
15 0
|
17天前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于MSER和HOG特征提取的SVM交通标志检测和识别算法matlab仿真
### 算法简介 1. **算法运行效果图预览**:展示算法效果,完整程序运行后无水印。 2. **算法运行软件版本**:Matlab 2017b。 3. **部分核心程序**:完整版代码包含中文注释及操作步骤视频。 4. **算法理论概述**: - **MSER**:用于检测显著区域,提取图像中稳定区域,适用于光照变化下的交通标志检测。 - **HOG特征提取**:通过计算图像小区域的梯度直方图捕捉局部纹理信息,用于物体检测。 - **SVM**:寻找最大化间隔的超平面以分类样本。 整个算法流程图见下图。
|
2天前
|
存储
基于遗传算法的智能天线最佳阵列因子计算matlab仿真
本课题探讨基于遗传算法优化智能天线阵列因子,以提升无线通信系统性能,包括信号质量、干扰抑制及定位精度。通过MATLAB2022a实现的核心程序,展示了遗传算法在寻找最优阵列因子上的应用,显著改善了天线接收功率。
|
4天前
|
监控 算法 数据安全/隐私保护
基于三帧差算法的运动目标检测系统FPGA实现,包含testbench和MATLAB辅助验证程序
本项目展示了基于FPGA与MATLAB实现的三帧差算法运动目标检测。使用Vivado 2019.2和MATLAB 2022a开发环境,通过对比连续三帧图像的像素值变化,有效识别运动区域。项目包括完整无水印的运行效果预览、详细中文注释的代码及操作步骤视频,适合学习和研究。
|
12天前
|
算法
基于粒子群算法的分布式电源配电网重构优化matlab仿真
本研究利用粒子群算法(PSO)优化分布式电源配电网重构,通过Matlab仿真验证优化效果,对比重构前后的节点电压、网损、负荷均衡度、电压偏离及线路传输功率,并记录开关状态变化。PSO算法通过迭代更新粒子位置寻找最优解,旨在最小化网络损耗并提升供电可靠性。仿真结果显示优化后各项指标均有显著改善。