【数据结构】堆的原理&实现

数据结构中的堆:原理、实现与应用详解 System.out.println("添加 " + num + " 后,中位数: " + finder.findMedian());System.out.println("Top " + k + " 最大值: " + findTopKMax(nums, k));System.out.println("Top " + k + " 最小值: " + findTopKMin(nums, k));System.out.println("节点[" + i + "]=" + heap[i] +// 存储较小的一半。 阅读详情

       🔥🔥 欢迎来到小林的博客!!
      🛰️博客主页:✈️林 子
      🛰️博客专栏:✈️ 数据结构与算法
      🛰️社区 :✈️ 进步学堂
      🛰️欢迎关注:👍点赞🙌收藏✍️留言

堆的性质

1.堆是一颗完全二叉树。

2.堆的每一个父节点都大于等于或小于等于它的子节点。

所有父节点都大于等于子节点的堆叫大堆。

所有父节点都小于等于子节点的堆叫小堆。

在这里插入图片描述

在这里插入图片描述

堆的实现

我们可以用链表或者数组的形式来实现堆。如果用链表来实现堆的话,那么我们需要定义一个二叉树节点的结构体。并至少要包括左孩子,右孩子,存储的值三个结构体成员。例如:

struct HeapNode
{
    HeapNode* _left;  //左孩子
    HeapNode* _right; //右孩子
    int _val;  //存储的值
};

而这也意味着一个节点至少必须包含了三个成员,这对空间是一种消耗。那么我们可以用数组来实现堆。因为堆是一个完全二叉树。那么用数组实现就不会存在中间有空间浪费的情况,也可以用父节点的下标 * 2 + 1计算出左孩子的下标。也可以用(子节点 - 1 ) / 2 来计算出其父节点的下标。我们把下面这个堆抽象成一个数组。

在这里插入图片描述

	template<class T,class Functor = Less<T>>
	class Heap
	{
	public:
		T* _hp;
		size_t _size;
		size_t _capacity;

用数组存储的话,那么它的逻辑图应该是这样的。

在这里插入图片描述

以20这个节点为例,它的下标是2,那么它的父节点所在的位置就是(2 - 1) / 2。也就是10的位置。它的左孩子则是2*2 + 1,也就是5这个位置。右节点则是 2 * 2 + 2。

我们理清楚了堆如何在数组中存储堆。那么我们就可以开始实现堆了。

堆的声明

我们创建一个堆的类。并引用模板,因为堆存储的值的类型是不确定的。而堆需要提供以下几个成员。

成员变量:

T* _hp : 指向堆内存(非此数据结构的堆)的一块空间,存储的是当前堆中的数据。

size_t _size : 记录堆的大小,也是下一次push时的下标位置

size_t _ capacity : 记录堆的容量,如果和_size相等,则说明需要扩容了

成员函数:

Heap(size_t capacity = 16); 构造函数,采用了缺省参数。也可以用户手动传入一个参数,指明堆的容量。

~Heap(); 析构函数,对当前对象动态资源的销毁

template<class T>
class Heap
{
private:
	T* _hp;
	size_t _size;
	size_t _capacity;
public:
    Heap(size_t capacity = 16);
    ~Heap();
}

普通构造和析构的实现

我们的构造函数只需要为_hp开辟空间,并初始化 _size 和 _capacity即可。析构函数直接释放 _hp即可。

构造函数

Heap(size_t capacity = 16):_capacity(capacity),_size(0){
			_hp = new T[_capacity];
		}

析构函数

~Heap() {
			delete _hp;
			_size = _capacity = 0;
		}

插入函数push

那么我们要往堆中插入数据怎么办,我们可以写个push函数来为堆插入数据。 那么在写这个函数之前,我们要知道堆是如何push的。

堆的push过程:

1.把插入的值放入数组的末尾(也是堆的最后一个叶节点)

2.对这个节点进行向上调整

什么是向上调整????

就是让当前节点与它的父亲进行比较,我们拿大堆来说,如果父节点比当前节点小。那么就交换这两个节点,一直循环直到父节点比当前节点到或者当前节点已经是根节点时才结束。 举两个例子,我们有一个大堆。

在这里插入图片描述

这时候我们要新增一个节点,35,那么我们先把它加在末尾。

在这里插入图片描述

然后让当前节点与它的父节点比较大小。如果当前节点比父节点大,则交换位置(大堆的情况下)。

在这里插入图片描述

随后再让该节点和它的父亲比较,比它的父亲小,调整完毕。

第二个例子

依旧是刚刚那个堆,只不过我们把插入的数据换成了70

在这里插入图片描述

那么它会一直调整到根节点才结束。如图

在这里插入图片描述

搞明白了向上调整的原理后。我们就可以写出push函数代码了!

push函数代码

void UpDateCapacity()
{
    T* tmp = new T[_capacity * 1.5];  //开辟一个新的堆
    assert(tmp); //断言,扩容失败则崩溃
    memcpy(tmp, _hp, _size * sizeof(T)); //转移资源
    delete _hp;  //释放旧空间
    std::swap(tmp, _hp); //交换两个地址
    _capacity = _capacity * 1.5; //更新容量
}
//交换两个数的值
void swap(T& x, T& y)
{
    T tmp = x; 
    x = y; 
    y = tmp;
}
void Up()
{
    //从最后一个开始向上调整
    int child = _size - 1; 
    int parent = (child - 1) / 2; 
    while (child) //child != 0 
    {
        //大堆 , 孩子大于父亲则交换
        if (_hp[child] > _hp[parent])
        {
            swap(_hp[child], _hp[parent]);
            child = parent; //更新孩子
            parent = (child - 1) / 2; //更新父节点
         }
        else break;
    }
}
void push(const T& val)
{
    if (_size == _capacity) //检查当前空间是否满了
    {
        //扩容 
        UpDateCapacity();
    }
    _hp[_size++] = val; //插入
    Up();  //向上调整
}

移除节点函数pop

堆移除末尾节点是没有意义的,堆pop的都是根节点,也叫做堆顶。因为堆顶不是最大的,就是最小的。所以我们的pop函数就是移除堆顶中的元素。当然不能直接移除,如果直接移除会破坏堆的结构。所以我们时必须让堆顶与末尾节点交换。随后让堆顶向下调整即可。

pop的流程:

1.堆顶位置与末尾位置进行交换。

2.堆顶开始向下调整

什么是向下调整?

和向上调整差不多,向上调整是和父亲比较后决定是否交换。向下调整也是。如果是大堆的情况下,父亲与较大的那个孩子比较大小,如果比较大的孩子比父节点的值要大。那么则交换,小堆的情况则相反。

那么我们来演示一下。还是刚刚那个堆,不过我们要把70这个节点pop掉。

在这里插入图片描述

第一步,我们让堆顶与末尾交换。

在这里插入图片描述

随后删掉末尾元素(很简单,就是_size–即可)。

然后我们要先让它的两个子节点进行比较,因为是大堆,所以取较大的那个,也就是50。再拿50和35进行比较,50大于35,则交换。

在这里插入图片描述

然后我们继续向下调整,可是此时它已经没有右孩子了。那么就直接和左孩子比较。比左孩子大,则结束。

整个流程图:

在这里插入图片描述

pop代码

原理弄明白之后,直接上代码。

void Down()
{
    int parent = 0; //父节点
    int child = parent * 2 + 1;  // 左孩子节点
    while (parent < _size) /
    {
        if (child + 1 >= _size - 1 && _hp[child + 1] > _hp[child])
            child++; //如果右孩子存在且右孩子 > 左孩子,那么child变成右孩子
        if (child >= _size - 1) break; //左孩子不存在
        if (_hp[child] > _hp[parent]) //子节点>父节点
         {
            swap(_hp[parent], _hp[child]); //交换
            parent = child; //更新
            child = parent * 2 + 1; 
        }
        else break;
    }
}
void pop()
{
    assert(_size > 0); //保证堆里有元素
    //根节点和最后一个节点交换
    swap(_hp[0], _hp[_size-- - 1]); //堆顶和末尾交换
    Down(); //向下调整
}

top函数

top函数是获取堆顶元素的函数,我们可以在保证堆里有元素的情况下直接返回_hp的第0个元素即可。

T top()
{
    assert(_size > 0);
    return _hp[0];
}

引入仿函数

我们上面演示的是大堆的情况下,但是如果我们又想让它在不写多个类的情况下,既可以用大堆,也可以用小堆,那么该如何实现呢?这里我们可以在模板参数中引入仿函数。

首先我们要有2结构体/类,并重载它们的()操作符,传入两个参数用来比较,Greate类比较 >,Less类 比较小于

template<class T>
    struct Greater
    {
        bool operator()(T& x, T& y)
        {
            return x > y;
        }
    };
template<class T>
    struct Less
    {
        bool operator()(T& x, T& y)
        {
            return x < y;
        }
    };

然后我们在类模板声明处加上一个类型,并设置缺省。

template<class T,class Functor = Less<T>> 
class Heap
{
	.....
};

这样我们的类中就有一个Functor类型了,我们可以用这个类型创建一个对象,这个对象及你创建Heap对象时传入的模板参数。传入Less则创建Less对象,传入Greater则创建Greater对象。不传则用缺省的。

随后我们就可以修改向上和向下调整的代码了

void Up()
{
    Functor func; //创建一个Functor对象
    //从最后一个开始向上调整
    int child = _size - 1; 
    int parent = (child - 1) / 2; 
    while (child) //child != 0 
    {
        //大堆
        if (func(child,parent)) //用Functor对象的()操作符重载返回的bool值来判断真或者假
        {
            swap(_hp[child], _hp[parent]);
            child = parent;
            parent = (child - 1) / 2;
        }
        else break;
    }
}

void Down()
{
    Functor func; //创建一个Functor对象
    int parent = 0;
    int child = parent * 2 + 1; 
    while (parent < _size)
    {
         //用Functor对象的()操作符重载返回的bool值来判断真或者假
        if (child + 1 >= _size - 1 && func(_hp[child + 1],_hp[child]))
            child++; //如果右孩子存在且右孩子 > 左孩子,那么child变成右孩子
        if (child >= _size - 1) break; //左孩子不存在
        if (func(_hp[child],_hp[parent])) //用Functor对象的()操作符重载返回的bool值来判断真或者假
        {
            swap(_hp[parent], _hp[child]);
            parent = child;
            child = parent * 2 + 1;
        }
        else break;
    }
}

这样我们堆的基本功能也实现了,当然还有拷贝构造,赋值重载,移动构造…并没有完善。由于我们只是演示堆的实现,所以这些函数就不实现了,大家有兴趣的话也可以实现一下。以下是演示中的所有代码。

template<class T>
    struct Greater
    {
        bool operator()(T& x, T& y)
        {
            return x > y;
        }
    };
//建大堆
template<class T>
    struct Less
    {
        bool operator()(T& x, T& y)
        {
            return x < y;
        }
    };

template<class T,class Functor = Less<T>>
    class Heap
    {
        public:
        T* _hp;
        size_t _size;
        size_t _capacity;

        public:
        Heap(size_t capacity = 16):_capacity(capacity),_size(0){
            _hp = new T[_capacity];
        }
        ~Heap() {
            delete _hp;
            _size = _capacity = 0;
        }
        private:
        void UpDateCapacity()
        {
            T* tmp = new T[_capacity * 1.5];  //开辟一个新的堆
            assert(tmp);
            memcpy(tmp, _hp, _size * sizeof(T));
            std::swap(tmp, _hp);
            _capacity = _capacity * 1.5;
        }
        //交换两个数的值
        void swap(T& x, T& y)
        {
            T tmp = x; 
            x = y; 
            y = tmp;
        }
        void Up()
        {
            Functor func;
            //从最后一个开始向上调整
            int child = _size - 1; 
            int parent = (child - 1) / 2; 
            while (child) //child != 0 
            {
                //大堆
                if (func(child,parent))
                {
                    swap(_hp[child], _hp[parent]);
                    child = parent;
                    parent = (child - 1) / 2;
                }
                else break;
            }
        }
        void Down()
        {
            Functor func;
            int parent = 0;
            int child = parent * 2 + 1; 
            while (parent < _size)
            {
                if (child + 1 >= _size - 1 && func(_hp[child + 1],_hp[child]))
                    child++; //如果右孩子存在且右孩子 > 左孩子,那么child变成右孩子
                if (child >= _size - 1) break; //左孩子不存在
                if (func(_hp[child],_hp[parent]))
                {
                    swap(_hp[parent], _hp[child]);
                    parent = child;
                    child = parent * 2 + 1;
                }
                else break;
            }
        }
        public:
        void push(const T& val)
        {
            if (_size == _capacity)
            {
                //扩容 
                UpDateCapacity();
            }
            _hp[_size++] = val;
            Up(); 
        }
        T top()
        {
            assert(_size > 0);
            return _hp[0];
        }
        void pop()
        {
            assert(_size > 0);
            //根节点和最后一个节点交换
            swap(_hp[0], _hp[_size-- - 1]);
            Down();
        }
    };
ST7789P3初始化配置 【代码】ST7789P3初始化配置。 阅读详情

相关推荐

SAP S4 MM模块自动记账全流程解析:从评估范围到科目分组的实战配置

本文深入解析SAP S4 MM模块自动记账的全流程,从核心概念评估范围与评估控制入手,详细阐述了评估类、科目分组等关键配置的逻辑关系。通过实战配置步骤,指导如何建立从物料移动(如收货、发料)到自动生成准确财务凭证的完整体系,确保库存价值与总账实时同步,为企业构建可靠的财务业务一体化基石。

weixin_29313547的博客 425

实现堆(push/pop)

堆可以用数组模拟。假设堆顶在arr[1],那么任意节点 i 的左右子节点分别是 2i 和 2i+1,父节点是i/2. 堆具有以下性质: 大顶堆:arr[i] &gt;= arr[2i] &amp;&amp; arr[i] &gt;= arr[2i+1] (i = 1,2…) 小顶堆:arr[i] &lt;= arr[2i] &amp;&amp; arr[i] &...

AgoniAngel 1951

利用Spm12进行fMRI数据分析:从预处理到结果解读的完整指南

本文提供了利用SPM12进行fMRI数据分析的完整流程指南,涵盖从数据预处理、统计建模到结果解读的全过程。详细介绍了在MATLAB环境下使用SPM12图形界面完成头动矫正、空间标准化等关键步骤的操作方法与避坑技巧,帮助神经科学研究者和心理学研究者高效处理功能磁共振成像数据并产出可靠结果。

weixin_29079671的博客 452

【数据结构】超详细——堆的实现

堆是二叉树的一种应用展现,与序列、链表等相比更有工程应用价值。

joes_ju的博客 2080

爬虫风控实战:当你的代理IP被数美滑块盯上时,如何优雅破解?

本文深入探讨了爬虫风控对抗中数美滑块验证码的破解与防御策略。通过分析数美滑块的多层防御机制,提出了代理IP池精细化管理、请求特征拟人化改造以及工程化滑块验证解决方案等系统性方法,帮助开发者有效降低验证码触发率,提升爬虫效率。

weixin_27419879的博客 207

Vision 机器视觉案例 之 零件边缘缺陷检测

缺陷检测工具

机器视觉李小白的博客 1387

堆-链表实现

小顶堆大顶堆的概念大家应该都很熟悉了,如果不了解,可以搜索一下,网上很多介绍,而且很多源码实现,都很简单。 不过从网上看了一些堆的实现,都是用数组的。但是数组有一个缺陷,需要扩展时,就要复制原来的内存,申请新的空间。所以我在想能不能用链表,发现还真可以,就凑凑写了个代码。最后代码是写完了,发现其实链表没有必要,而且会占用更多的内存,尤其是对于那种int型变量,过多的指针真是浪费了大量内存。如果真

羽飞的专栏 3129

tsmc12: m0po max length问题(H384.M0_PO.L.1)

手动调整可以挪cell,制造上下两个row相对的至少一个site的空间,通过插普通filler来解决,这里需要注意的是,tsmc12有via0的规则,需要让via0落在via0 grid上。在pt eco之后会有一些m0po max length问题出现,大部分问题都可以通过替换decap来解决,少部分由于局部density过高,需要手动调整。更多学习内容请关注「拾陆楼」知识星球。#ICC2中替换decap的参考脚本。

m0_61544122的博客 792

数据结构:堆概念复习及相关算法题整理

堆相关数据结构复习

qjyws的博客 685

【Pix4d精品教程】pix4d mapper相机未校准后手动添加连接点完美案例图文教程

如图所示,红色的照片为未校准的图片,软件无法自动获取连接点,有关相机未校准的原因及解决办法,可以参考《pix4d未校准相机:287 out of 402 images calibrated (71%), all images enabled, 6 block,问题分析及解决方案汇总》,本文以案例的形式,详细讲解pix4d中手动添加连接点的方法及操作步骤。 文章目录1. 手动添加连接点2. 重新优化3. 生成质量报告,检查精度 1. 手动添加连接点 在【空三射线】模式下查看校准失败的图片,记下照片的名称。.

智慧空间实验室 2万+

(汇总篇)语义SLAM相关开源方案| 全球优秀作者与实验室 | SLAM学习资料整理

SLAM 与深度学习相结合的工作当前主要体现在两个方面,一方面是将语义信息参与到建图、位姿估计等环节中,另一方面是端到端地完成 SLAM。针对建图的工作一方面是利用几何信息进行稠密重建,另一方面很多工作利用语义信息达到了很好的语义重建效果,三维重建、SFM。动态 SLAM 也是一个很值得研究的话题,这里不太好分类,很多工作用到了语义信息或者用来三维重建,收集的方案相对较少。优化可能是 SLAM 中最难的一部分了吧 +_+ ,一般都是直接用现成的因子图、图优化方案,要创新可不容易。

熊猫小妖的AI世界 7870

堆的实现(堆的建立及push、pop元素)

堆数据结构是一种数组对象,它可以被视为一棵完全二叉树结构。堆结构的二叉树存储:大堆:每个父节点的都大于孩子节点;小堆:每个父节点的都小于孩子节点。建堆:由于堆被视为完全二叉树,故在h-1层找到第一个(从后往前找)非叶子结点,进行堆的下调建大堆时,从下往上依次判断并调整堆,使该结点的左右子树都满足大堆建小堆时,从下往上依次判断并调整堆,使该结点的左右子树都满足小堆可见大堆的建立...

weixin_33737134的博客 778

激光除草技术原理与应用全解析

激光除草技术通过光热、光化学等效应精准破坏杂草组织,核心参数包括功率(20-6000W)、波长(400nm-10.6μm)和脉冲宽度。主要应用于大田作物(如玉米、棉花)、经济作物(烟草、果树)及城市绿化,具有环保(无化学污染)、高效(识别率≥95%)和非接触等优势,但存在设备成本高(20-50万元)、技术门槛高等局限。当前技术融合AI识别、多光谱协同等创新,国产设备如华工智耘已实现95.3%识别精度。虽短期投入较高,但长期可降低30%除草成本,并带来环境效益(每亩减排1.2吨CO₂)

start_up_go的博客 557

C++数据结构详解——堆

1.堆的原理精讲 最大堆特点: 当然,也有最小堆,最小堆就是将最大堆反过来,根结点为最小值~ 堆是树中最有个性的树,他是用数组表示的树 。 2.在数组中快速创建堆算法 1.首先我们需要找到最后一个结点的父结点如图(a),我们找到的结点是 87,然后找出该结点的最大子节点与自己比较,若该子节点比自身大,则将两个结点交换。 图(a)中,87 比左子节点 95 小,则交换之。如图(b)所示 2.我们移动到第一步前一个父节点 93,如图(c)所示.同理做第一步的比较...

qq_54169998的博客 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

数据结构——最小堆的实现总结

堆的实用性 编程过程中,时常会遇到一种模型,我们收集到一些数据,并对其处理,但是我们需要首先处理这些数据中具有最小关键码或者最大关键码(Key:可以是根据数据的先后顺序或重要程度等给数据编的号码)的数据。我们希望有一种数据结构能够支持插入操作并能方便的从中取出具有最小或最大关键码的记录,这样的数据结构即为优先级队列,优先级队里的实现方式有多种,其中最高效的一种便是堆(heap)。堆的种类 堆有最

razorEdge的博客 1万+

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

数据结构 —— 堆

堆是一种特殊的树形数据结构,称为“二叉堆”(binary heap)看它的名字也可以看出堆与二叉树有关系:其实堆就是一种特殊的二叉树堆的性质:堆中某个结点的值总是不大于或不小于其父结点的值;堆总是一棵完全二叉树。

2301_78957570的博客 3006

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

【数据结构】堆——超详解!!!(包含堆的实现)

本文详细讲解了堆这一数据结构的概念、分类及实现方法。堆是一种特殊的完全二叉树,分为大堆(父节点值≥子节点)和小堆(子节点值≥父节点),其特点是根节点值为最大或最小。文章以数组实现小堆为例,介绍了堆的创建、初始化、销毁等基本操作,重点讲解了插入数据时的动态扩容机制和向上调整算法。通过头文件与源文件分离的模块化编程方式,提供了完整的堆实现代码,包括断言检查、内存管理等健壮性设计。该实现可用于高效查找极值,是学习数据结构与算法的重要基础。

zore__的博客 1776

数据结构—堆(Heap)的原理介绍以及Java代码的完全实现

详细介绍了—堆(Heap)这种数据结构的特点和原理,并且提供了Java代码的完全实现,包括大顶堆、小顶堆的构建,堆节点的添加、删除,大顶堆、小顶堆的排序等方法!

终生学习践行者 5954

【数据结构】——堆的实现与算法

对比向上调整建堆,h-1层向下调整只需要移动1层,而向上调整需要移动h-1次因此向下调整是更优的建堆算法。插入一个数据后不再是小堆需要将新数据调整到合适的位置,所以堆的插入就是在数组插入数据再向上调整即可。剩下数据与堆顶数据比较,如果比堆顶数据大,那么替代堆顶进堆(覆盖堆顶数据然后向下调整)堆插入的过程其实就是建堆,在一个堆的末尾插入数据然后向上调整形成一个新的堆。Top—K问题:N个数中求最大的(最小的)前K个数据,一般N远大于K。<2>数据比堆顶数据大,覆盖调整之后形成一个新的小堆,再次比较。

2402_82668782的博客 2018

【数据结构与算法】探索数组在堆数据结构中的妙用:从原理到实现

堆是一种特殊的树形数据结构,其每个节点的值都大于或等于(大顶堆)或小于或等于(小顶堆)其子节点的值。在计算机科学中,堆常用于实现优先级队列、堆排序等算法。本文将探讨如何使用数组实现堆,并分析其原理、实现细节以及应用场景。

倔强的石头的博客 2142

【数据结构】堆的实现

基本思想: 向堆尾插入新元素时,维护堆的性质,需要对该元素向上调整,从新插入的节点开始,与其父节点比较,若新节点的值比其父节点的值小,则交换它们,并将新节点的父节点当作目标节点继续向上调整,若目标结点的值比其父结点的值大,就停止向上调整,此时该树已成堆。(以小堆调整为例) 若想将此二叉树调整为小堆,左右子树都必须是一个小堆,才能调整。 若想将此二叉树调整为大堆,左右子树都必须是一个大堆,才能调整。

2302_81312180的博客 1297

堆的原理及实现

文章目录1 堆的原理2 堆的实现2.1 堆的创建 1 堆的原理 先看一下堆长什么样: 最大堆的特点: 每个结点最多可以有2个子结点。 根结点的键值是所有堆结点值中的最大者,且每个结点的值都比其孩子的值大。 除了根结点没有兄弟结点,最后一个左子结点可以没有兄弟结点,其他结点必须有兄弟结点。 看一下如下几个符不符合最大堆的定义: (A、B不是,C是最大堆。) 看一下堆的特点: 堆是你见过的最...

木子皿--啥都不会的菜鸟 1025

数据结构:堆和堆排序

堆和堆排序

AlanTZT的博客 1677

【数据结构】堆的讲解与实现

文章目录堆的结构分析堆的实现堆的存储结构堆初始化堆的插入push向上调整堆判空堆删除pop向下调整堆销毁运行结果时间复杂度分析源代码堆的经典应用 堆的结构分析 需要注意的是堆是一种数据结构,与操作系统的堆区没有关系。 堆的结构:堆是完全二叉树,从左到右是连续的,适合用数组存储 堆是一颗完全二叉树,分为大堆和小堆 大堆:一个树中,任何父亲节点都大于等于孩子节点,所以大堆的根节点最大 小堆:一个树中,任何父亲节点都小于等于孩子节点,所以小堆的根节点最小 堆的实现 了解过顺序表的小伙伴,对堆的实现就非常简

weixin_46016019的博客 1592

数据结构与算法——堆的原理和实现

目录 一、堆的原理 二、堆的实现 1.堆的定义 2.堆的初始化 3.向上调整算法 4.向上调整算法代码实现 5.堆的插入 6.向下调整算法 6.堆的删除 7.堆的大小 8.判断堆是否为空 总结 一、堆的原理 堆(英语:Heap)是计算机科学中的一种特别的完全二叉树。若是满足以下特性,即可称为堆:“给定堆中任意节点P和C,若P是C的母节点,那么P的值会小于等于(或大于等于)C的值”。若母节点的值恒小于等于子节点的值,此堆称为最小堆(min heap);反之,若母节点的..

m0_62179366的博客 2369

数据结构(堆)的代码实现和测试——堆的原理及代码实现

由于堆是由数组实现的完全二叉树,因此我们每次插入新的元素只能将其按顺序放在数组的末尾,然后再进行上推操作将其放到合适的位置(因为此时新元素处于叶子节点,只能上推)由于完全二叉树的特性,前 n / 2 个节点全部为非叶子节点,所以我们只需对n/2 个节点全部进行下推操作完毕即可。所以,堆的存储用数组来实现,而其左右子树以及父亲节点的位置关系依靠数学计算来推导。如果上推成功,那么下推自然推不下去,如果上推不成功,也不影响后面下推的操作。因此,最大堆的根节点是整个堆中最大的,最小堆的根节点是整个堆中最小的。

2302_80225397的博客 1062
上一篇: Git用法指南(建议收藏)
下一篇: 【Linux】环境变量
林   子
博客等级 码龄4年 2671粉丝 64原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林 子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值