堆

【数据结构】筛选法建堆 给你一个顺序表或数组(一串数据),通常来说建堆有两种方法一种**堆向上调整算法**,一种**堆向下调整算法建堆**也就是**筛选法**建堆。 筛选法建堆是一种快速建堆的方法,它是在堆排序算法中使用的。这种方法的基本思想是通过不断筛选节点,如果建大堆就将大的节点向上筛选,小的节点向下筛选,小堆就反之,最终得到一个有序的堆。 阅读详情

一、堆的初始化
1、堆的概念
堆实际上是一种完全二叉树,堆可分为大堆和小堆。大堆就是左右孩子的值都小于其父节点的值,根节点的值最大;小堆就是左右孩子的值都小于其父节点的值,根节点的值最小。
2、建堆
第一步:先给出一个数组
这里写图片描述

第二步:根据该数组,将其构建成完全二叉树的结构
这里写图片描述
第三步:以这个完全二叉树为基础构造初始堆,从最后一个非叶子节点开始向上调整,这里以小堆为例
这里写图片描述
这里对以上调整过程加以解释说明:
(1)调整的时候从最后一个非叶子节点向上调整,设最后一个非叶子节点的位置为index,数组的大小为size,则index=size/2-1。
如上图:最后一个非叶子节点的位置为4,数组的大小为10,则4=10/2-1。
(2)向最后一个非叶子节点开始调整的过程是:
先比较左右孩子的大小,找出左右孩子中较小的那一个;
然后将左右孩子中较小的那一个与其父节点进行比较,如果父节点较大就进行交换,否则就去调整下一棵子树。
第四步:代码实现

template <class T>
class Heap
{
public:
    //缺省的构造函数
    Heap()
    {}

    Heap( T* a, size_t size)
    {
        //将数组中的数据放到顺序表里面
        for (size_t i = 0; i < size; i++)
        {
            _a.reserve(size);
            _a.push_back(a[i]);
        }
        //进行调整
        for (int i = _a.size() / 2 - 1; i >= 0; --i)
        {
            _AdjustDown(i)
        }

    }
    protected:
    void _AdjustDown(int root)
    {
        int left = root * 2 + 1;
        int right = left + 1;
        //如果左孩子不存在,则root为叶子节点,已不需再调整
        while (left < _a.size())
        {
            //找出左右孩子中较小的那一个
            int min = left;
            //注意判断右孩子有没有越界
            if (right<_a.size() &&
             _a[left]>_a[right])
            {
                min = right;
            }
            //找出左右孩子中较小的那一个与父节点进行比较
            if (_a[min] < _a[root])
            {
                swap(_a[min], _a[root]);
                root = min;
                left = root * 2 + 1;
                right = left + 1;
            }
            else
                break;
        }
    }
    private:
    vector<T> _a;
};

二、相关操作
1、向堆中插入元素,并保证堆的性质
(1)、步骤
步骤一:向存储堆的顺序表中push进去一个数据x;
步骤二:从堆的最后一个叶子节点开始向上调整
(2)、举例说明
这里写图片描述
(3)、代码实现

//向堆尾插入元素
    void Push(int x)
    {
        _a.push_back(x);
        _AdjustUp(_a.size() - 1);
    }

//从最后一个叶子节点开始往上调整
    void _AdjustUp(int root)
    {
        int child=root;
        while (child > 0)
        {
            int parent = (child - 1) / 2;
            if (_a[child] < _a[parent])
            {
                swap(_a[child], _a[parent]);
                child = parent;
            }
            else
            {
                break;
            }
        }
    }

2、删除堆顶元素
(1)、步骤
步骤一:将堆顶元素和最后一个非叶子节点进行交换;
步骤二:将交换后的最后一个非叶子节点删除;
步骤三:从堆顶开始往下进行调整
(2)、举例说明
这里写图片描述
(3)、代码实现

    //删除堆顶元素
    void Pop()
    {
        swap(_a[0], _a[_a.size() - 1]);
        _a.pop_back();

        _AdjustDown(0);
    }

三、堆排序
1、算法描述
堆排序实际上是一种选择排序,如果想要降序排列,则先构建一个小堆,设小堆的大小为size
步骤一:先将堆顶元素和最后一个元素进行交换;
步骤二:将size减1,缩小堆的大小,即不包括最后一个元素;
步骤三:将size缩减后再进行调整,即除过最后一个元素之外,将剩下的元素调整成小堆结构。
2、举例说明
这里写图片描述
3、代码实现

void HeapSort(int n)
    {
        //先调成小堆结构
        for (int i = _a.size() / 2 - 1; i >= 0; --i)
        {
            _AdjustDownSort(i, n);
        }

        int end = n - 1;
        while (end)
        {
            swap(_a[0], _a[end]);
            _AdjustDownSort(0, end);
            --end;
        }
    }

//从最后一个非叶子节点开始调整(排序用)
    void _AdjustDownSort(int root,int n)
    {
        int left = root * 2 + 1;
        int right = left + 1;
        //如果左孩子不存在,则root为叶子节点,已不需再调整
        while (left < n)
        {
            //找出左右孩子中较小的那一个
            int min = left;
            //注意判断右孩子有没有越界
            if (right<n && _a[left]>_a[right])
            {
                min = right;
            }
            //找出左右孩子中较小的那一个与父节点进行比较
            if (_a[min] < _a[root])
            {
                swap(_a[min], _a[root]);
                root = min;
                left = root * 2 + 1;
                right = left + 1;
            }
            else
                break;
        }
    }

说明:由于每一调整的范围不同,因此_AdjustDownSort()函数需要两个形参,所以该函数与上面的调整函数不太相同。

用筛选法求100以内的素数 筛选法就是“埃拉托色尼筛法”,方法是在纸上写出1~1000的全部整数,然后逐个判断他们是否为素数,挖掉非素数,剩下的就是素数。 算法思想: 1、挖掉1 2、用下一个未被挖掉的数p除p后面各数,把p的倍数挖掉 3、检查p是否小于√p的整数部分,如果是,则返回2继续执行,否则结束 4、剩下的数就是素数 代码: #include<cstdio> #include<math.h> int main(){ int a[101],n=0; for(int i=1;i<=100;i++ 阅读详情

相关推荐

堆的原理实现详解以及堆的应用

文章目录堆是什么堆的存储方式插入结点删除结点堆排序代码实现 堆是什么   堆(heap)本质上就是一棵完全二叉树,只不过这棵完全二叉树有点特别,能够被称为堆的二叉树,除了它必须要是一棵完全二叉树外,它的每一个结点都必须大于或者小于其子节点。 解释一下就是对于树中的所有的结点都至少有一棵子树,对于这个结点的子树上所有的结点都必须要大于或者小于其父节点。因此,堆也是个递归的定义,通常,我们将结点都大于或者等于子树所有结点的堆称为最大堆 ;将结点都小于或者等于子树所有结点的堆称为最小堆 。如下图所示:

Lessen的博客 1488

堆排序之建初始堆

在牛客网上看到一道题 答案是c,但是之前只接触插入法建堆,没了解筛选法建初始堆,于是网上冲浪,查找了一波解析,于是有了现在这个思路总结(看半天也没有看到比较靠谱的代码),然后总结了一下,按照这种思路,能得到C答案,但仍然存在一点疑惑(初始堆难道不应该是大顶堆或者小顶堆嘛,这结果也不是呀,还是说,有什么定义我不知道?求解),需要再去看看书。。。 最终还是觉得答案是错的,按照概念重新更正了图解...

学习小记 4万+

二项堆与斐波那契堆

二项堆 二项堆是符合最小堆性质的二项树链接成的森林二项树是形如下图的树

小虎 的博客 2098

堆排序(选择类排序)

目录一、堆的定义二、堆与序列的关系三、算法思想3.1 建立初始堆3.2 重建堆3.2.1 过程分析3.2.2 算法实现3.3 堆排序 第一次循环 第二次循环 第三次循环

狂放不羁霸的博客 8296

acm-【堆】学习笔记(二叉堆、左偏树、配对堆、斐波拉契堆、斜堆、STL)

引言 本文主要针对作者本人复习使用,相关基础知识点不会讲述。 目录引言二叉堆左偏树斜堆配对堆二项堆斐波拉契堆STL中的堆堆的应用 二叉堆 二叉堆是最普通的堆,能够实现push,poppush,poppush,pop等基本操作,下面以小根堆为例给出一种常见的实现。 首先设置一个足够大的数组,我们将树的节点按照层次遍历的顺序从小到大依次放置在数组中,数组中的位置也对应是该节点的编号,如下图所示: 上图是一个典型的二叉树,每个节点上标注的数字即是该节点的编号,容易发现对于一个节点uuu而言,它的儿子分别是2u,

qq_30361651的博客 1476

linux 驱动 - pinctrl子系统

分析总结 pinctrl 子系统框架结构,平台 mtk6771 内核版本 kernel-4.4 , 本文所有的分析均基于此版本。

sty01z的博客 1557

堆排序

#include /*非递增排序*/ void swap(int k[], int i, int j) { int temp; temp = k[i]; k[i] = k[j]; k[j] = temp; } void Heapadjust(int k[], int s, int n) { int i, temp; temp = k[s]; //临时变量存放当前需要调整的双亲结点。

PengPengBlog的博客 3027

power bi 演唱会-佐罗

我是业务分析人员,注重使用性,因此,课程不到 30% 的内容就可以解决目前为止我碰到的所有业务问题,剩下的 70% 内容是帮助我提升,优化,升华,精益求精用的,比如第三方工具,比如代码运行速度优化,比如查询逻辑优化等等。系统性上来说,结构明晰,安排上非常有条理,层层递进;《BI 真经》,中有真经二字,略显夸大,而当我第一次证明了这点的时候,我也非常惊讶,这就是我做以下所有事情的一切动力。《BI 真经》综合考量思想性,系统性,本质性,创新性,通用性,技巧性,启发性,对比其他课程有压倒性的显著优势。

v_1090213742的博客 911

堆(什么是堆以及怎样自己创建堆)

一篇文章教你认识什么是堆以及自己如何创建堆

不能再留遗憾了的博客 2449

Shader Graph入门

Shader Graph 简介

zaizai1007的博客 1万+

手把手教你使用transciver-ip核的配置

手把手教你使用transciver-ip核的配置

u012938458的博客 5413

堆的实现以及利用堆进行排序

堆是一种特殊的完全二叉树,分为最大堆和最小堆。在最小堆中,父节点的值总是小于或等于其子节点的值。这种特性使得堆的根节点始终是所有节点中的最小值,非常适合实现优先队列。堆中某个结点的值总是不⼤于或不⼩于其⽗结点的值;堆总是⼀棵完全⼆叉树。⼆叉树性质对于具有 n 个结点的完全⼆叉树,如果按照从上⾄下从左⾄右的数组顺序对所有结点从0 开始编号,则对于序号为 i 的结点有:若 i>0 , i 位置结点的双亲序号: (i-1)/2;i=0 , i 为根结点编号,⽆双亲结点。

zzh_Zao的博客 1838

wvp gb28181 pro 平台国标级连功能说明

国标28181不同平台之间支持两种连接方式,平级和上下级,WVP目前支持向上级级联。

zengliguang的专栏 3887

Java——堆

九月在老家是收割水稻的月份,每次打完水稻,农民伯伯就会拿稻杆累成一堆。我觉得这个稻杆堆和数据结构堆外形有点相似哈。**堆是一棵完全二叉树,**但是这个完全二叉树要满足条件:其中任意一个结点要 >= 其左孩子结点和有孩子结点,这叫大根堆;其中任意一个结点要

m0_74100417的博客 1804

我的python学习之路

Python 是一门功能强大且易于学习的编程语言,广泛应用于数据分析、人工智能、Web 开发、自动化等领域。以下是一个 Python 学习路径的总结,帮助你系统地掌握 Python 编程。

数据知道的博客 3万+

【深度学习驱动流体力学】采集OpenFOAM仿真数据作为AI模型训练数据集与卷积神经网络搭建到预测(一站式完整代码实现)

采集OpenFOAM仿真数据作为AI模型训练数据集与卷积神经网络搭建到预测(一站式完整代码实现)

源代码杀手的博客 1414

【堆】堆的基本概念及操作,堆与优先队列

Heap;

2401_87820834的博客 2213

YOLOv11改进策略【模型轻量化】| 替换骨干网络 CVPR-2023 FasterNet 高效快速的部分卷积块

本文记录的是基于FasterNet的YOLOv11轻量化改进方法研究。FasterNet的网络结构借鉴 CNN 的设计理念,通过提出的PConv减少推理时的计算和内存成本,同时减少通道数并增加部分比例,降低延迟,并通过后续的PWConv来弥补特征信息可能缺失的问题,提高了准确性。本文在替换骨干网络中配置了原论文中的和六种模型,以满足不同的需求。

Limiiiing的博客 2030

什么是堆

堆是一种特殊的树,只要满足下面两个条件,它就是一个堆: (1)堆是一颗完全二叉树; (2)堆中某个节点的值总是不大于(或不小于)其父节点的值。 其中,我们把根节点最大的堆叫做大顶堆,根节点最小的堆叫做小顶堆。 堆详解 满二叉树 满二叉树是指所有层都达到最大节点数的二叉树。比如,下面这颗树: 完全二叉树 完全二叉树是指除了最后一层其它层都达到最大节点数,且最后一层节点都靠左排列。比如,下面这颗树: 可见,其实满二叉树是一种特殊的完全二叉树。 那么,使用什么结构存储完全二叉树最节省空

每天叫醒自己的不是闹铃 是娟 是梦 是理想。 8203

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

数据结构中的堆--堆的定义、调整堆、建堆、自定义堆

一、堆的定义 1.结构特点 堆(数据结构)和Java语言中提到的堆没有一点关系。 逻辑上:完全二叉树 物理上:数组 堆是一种顺序存储结构(采用数组方式存储),仅仅是利用完全二叉树的顺序结构的特点进行分析。 2.结点下标计算公式(根节点从0开始) 已知二叉树根结点的下标是root,那么它左孩子的下标left=2*root+1,右孩子的下标right=...

smell201611010513的博客 1万+

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

【数据结构】【堆】堆的建立、插入和删除

目录堆的介绍用数组表示堆,如何区分父节点和子节点?堆的种类?堆的插入、删除操作几个基本操作堆的插入堆的删除 感谢简书[唐先僧]的博文数据结构:堆(Heap),本博文有部分借鉴内容。 堆的介绍 堆是一个有固定顺序的完全二叉树,通常用数组来表示。 用数组表示堆,如何区分父节点和子节点? 下图是一个堆常用的编号方式示意图:根节点编号为0,根节点的左子节点编号为1、右子节点编号为2,再往下是3、4、5、6……即按照从上往下、从左往右的顺序编号。 在数组中,就按照如上所述的下标进行保存,如上图保存为数组就是{10,

怕走崎岖路,莫想登高峰 8991

【堆】堆排

相信看到这篇文章的柚柚们对于堆这个数据结构有啦一定的了解,至少清除堆是什么啦,当然可能有些柚柚们还不了解堆,可以去看博主之前写的关于堆(Heap)的博客喔链接在这里点击即可~堆排:顾名思义是利用堆这种数据结构所设计的排序算法。

2301_80085602的博客 1049

【堆】二分堆的实现以及STL中的堆

堆的概念binary_heap就是一种完全二叉树,也就是说整棵二叉树除了最底层的叶节点之外,是填满的,而最底层的叶节点由左至右又不得有空隙。底层实现就是一个数组 vector。 如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:Ki <= K2*i+1 且 Ki<= K2*i+2(Ki >= K2*i+1 且

菜鸟成长记 2323

堆的性质、堆的实现、堆排序

目录 一、堆的性质 二、堆的实现 1. 存储方式 2. 向堆中插入元素 3. 删除堆顶元素 4. 其他操作 5. 完整代码 三、堆排序 1. 原地建堆 2. 排序 3. 完整代码 4. 建堆的复杂度:O(n) 5. 堆排序的复杂度:O(nlogn) 6. 和快速排序的比较 一、堆的性质 堆是一种特殊的树。 只要满足以下两点,它就是一个堆: 堆是一个完全二叉树; 堆中每一个节点的值都必须大于等于(或小于等于)其子树中每个节点的值。 第一点,堆必须是一个完全二叉树。完全二.

马小超 5631

java中堆总结

堆heap」是一种满足特定条件的完全二叉树,主要可分为两种类型,如图8‑1所示。‧「小顶堆minheap」:任意节点的值≤其子节点的值。‧「大顶堆maxheap」:任意节点的值≥其子节点的值。堆通常用于实现优先队列,大顶堆相当于元素按从大到小的顺序出队的优先队列。从使用角度来看, 我们可以将“优先队列”和“堆”看作等价的数据结构。/*初始化堆*///初始化小顶堆//初始化大顶堆(使用lambda表达式修改Comparator即可)

2302_81054350的博客 1049
上一篇: 栈
下一篇: 快速排序
LP9127
博客等级 码龄11年 15粉丝 47原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值