手写堆与堆的常见操作

C++STL堆操作 C++STL堆操作并没有什么用的更新时间定义原因某玄学方法 并没有什么用的更新时间 【2019/02/21】 17:55 第一次更新(疑似更完) 定义 优先队列 需要调动到#include<queue>,以下以a为例: 大根堆的调用:priority_queue<int>a; 小根堆的调用:priority_queue<int,vector<int&amp 阅读详情

什么是堆

堆是一种特殊的树形数据结构,它满足以下两个条件:
堆是一个完全二叉树:即除了最后一层外,每一层都是满的,且最后一层上的节点都集中在左侧。
堆中每个节点的值都要大于等于(或小于等于)其子节点的值:如果每个节点的值都大于等于其子节点的值,我们称之为“大根堆”;如果每个节点的值都小于等于其子节点的值,则称之为“小根堆”。
堆通常用来实现优先队列,通过维护堆顶元素的位置和值,可以快速取出当前队列中的最小(或最大)值,并且支持插入、删除、修改操作。堆排序算法就是利用堆这种数据结构来实现的。
堆可以使用数组来存储,通过下标计算父节点、左右子节点的位置,具有空间效率高、插入、删除元素的时间复杂度为O(log n)等优点,在算法设计中得到广泛应用。

如何建堆(以小根堆为例)

在这里先说下堆的两个操作 down(int x) 和up(int x) 操作.

void down(int x)
{

    int temp = x; //左右孩子中最小值
    if(  2*x <= t &&   h[2*x] < h[temp]) temp =2*x;
    if(2*x + 1 <= t && h[2*x + 1] < h[temp]) temp = 2*x + 1;
    if(temp !=x) {

        swap(h[x],h[temp]);
        down(temp); //递归下去直到没有孩子或本身为最小值结束
    }

}

down和up的说明

  • down()使得大的元素节点向下沉.
  • up()使得小的元素向上浮.------------像极了在水里.堆中最小值为h(1).

用一维数组的方式来存储,下标从1开始,因为来是一个完全二叉树,从上到下在从左到右遍历,结点的编号是从1-n.每个结点若存在左孩子节点,则左孩子节点的编号为2*i,同理,右孩子节点的编号为2*i+1.一个节点的父节点的编号为i/2(i/2已经是向下取整).那么,新建小根堆时,孩子节点总大于等于其根节点.堆(看成完全二叉树)的最后一层元素最多为 n/2.从下向上看,第二层元素最多为 n/4n,第三层为n/8,第n层为n/2^n.
于是建堆完全可以使用down()操作完成,从n/2个节点开始,down()的操作规模:
n/21+n/42+n/83+……+n/2^n(n-1)(等差数列/等比数列求和)->错位相减 ->结果<(小于) n .所以建堆的时间复杂度近视于O(N).

代码实现(可以用down建堆,也可以用up建堆)

   for(int i = n/2; i;i--) down(i); //完全二叉树的性质,小于等于n/2的节点为分支节点. 大于n/2的为叶子节点

或者是(up建堆)

void up(int x)
{
   
   while(x/2 &&  h[x] < h[x/2])
   {
       swap(h[x],h[x/2]);
       x/=2;
       
   }
}

堆的相关操作

  1. 插入一个数 heap[ ++ size] = x; up(size);
  2. 求集合中的最小值 heap[1]
  3. 删除最小值 heap[1] = heap[size]; size – ;down(1);
  4. 删除任意一个元素 heap[k] = heap[size]; size – ;up(k); down(k);
  5. 修改任意一个元素 heap[k] = x; up(k); down(k);

修改和删除任意一个元素up和down操作只会执行一次.两个都写,但up()和down()内做了判断.

堆排序



#include "iostream"

#include "algorithm"
using namespace std;
const int N = 1E5+10;
int h[N];
int n,m,t;
void down(int x)
{

    int temp = x; //左右孩子中最小值
    if(  2*x <= t &&   h[2*x] < h[temp]) temp =2*x;
    if(2*x + 1 <= t && h[2*x + 1] < h[temp]) temp = 2*x + 1;
    if(temp !=x) {

        swap(h[x],h[temp]);
        down(temp); //递归下去直到没有孩子或本身为最小值结束
    }

}
int main()
{
    cin>>n>>m;
    t = n;
    for(int i = 1 ; i <= n ;i++)
    {
        cin>>h[i];
    }

    for(int i = n/2; i;i--) down(i);

    while(m--)
    {
         printf("%d ",h[1]);
         h[1] = h[t--];
        down(1);
    }



    return 0;
}


堆的相关操作(代码实现)

  1. 插入一个数 heap[ ++ size] = x; up(size);
  2. 求集合中的最小值 heap[1]
  3. 删除最小值 heap[1] = heap[size]; size – ;down(1);
  4. 删除任意一个元素 heap[k] = heap[size]; size – ;up(k); down(k);
  5. 修改任意一个元素 heap[k] = x; up(k); down(k);
案例代码

#include "iostream"

#include "algorithm"
using namespace std;
const int N = 1E5 + 10;
int h[N];
int n, m, t; //t为size大小




void up(int x)
{
    while (x / 2 && h[x] < h[x / 2])
    {
        swap(h[x], h[x / 2]);
        x /= 2;

    }
}


void down(int x)
{

    int temp = x; //左右孩子中最小值
    if (2 * x <= t && h[2 * x] < h[temp]) temp = 2 * x;
    if (2 * x + 1 <= t && h[2 * x + 1] < h[temp]) temp = 2 * x + 1;
    if (temp != x) {

        swap(h[x], h[temp]);
        down(temp); //递归下去直到没有孩子或本身为最小值结束
    }

}

//求堆里的最小值
void getmin()
{
    int ret = h[1];
 
    cout << "最小值为" << ret << endl;
     
}

// 插入一个数
void insert(int x)
{

    h[++t] = x;
    up(t);
    cout << "插入成功" << endl;

}
//删除最小值
void delMin()
{
    h[1] = h[t];
    t--;
    down(1);
    cout << "删除成功" << endl;
}
//删除任意一个元素 下标为k
void delKnum(int k)
{
    h[k] = h[t];
    t--;
    down(k);
    up(k);
}

//修改任意一个元素  修改下标为k的数的值为x
void modifyKnum(int k, int x)
{
    h[k] = x;
    up(k);
    down(k);

}


void menu()
{
    cout << "1:求堆里的最小值\r\n";
    cout << "2:插入一个数\r\n";
    cout << "3:删除最小值\r\n";
    cout << "4:删除任意一个元素\r\n";
    cout << "5:修改任意一个元素\r\n";
}
int main()
{
    cin >> n >> m;
    t = n;
    for (int i = 1; i <= n; i++)
    {
        h[i] = i;

    }

    for (int i = n / 2; i; i--) down(i);

   
    int op = 0;
    do {
        menu();
        cout << "输入操作数" << endl;
        cin >> op;
        switch (op)
        {

        case 1:
            getmin();
            break;
        case 2: {
            int x = 0;
            cin >> x;
            insert(x);
        }
            break;
        case 3:
            delMin();
            break;
        case 4:
        {


            int k = 0;
            cin >> k;
            delKnum(k);

        }
            break;
        case 5:
        {

            int k, x;
            cin >> k >> x;
            modifyKnum(k, x);

        }
            break;
        default:
            break;
        }

    } while (op != 0);
     


    return 0;
}
 
SAP 物料的分割评估 SAP 物料的分割评估 前言 本文主要讲解SAP中物料的分割评估,通过分割评估来区分出同一物料不同来源下的核算方式。例如:同一物料分为自产或者采购,或者同一物料分为进口或者国内采购等。 一、概述 分割评估一般用于以下场景: 1、物料分为内部采购和外部采购; 2、物料分属于进口或者国内采购; 3、物料分属于不同的批次; 4、物料分为自制或者采购。 由于物料的来源不同可能导致物料的价格或者性质不同,需要用不同价格来区分出 二、配置步骤 1.激活分割评估 ... 阅读详情

相关推荐

视频倍速 - 在线调倍速的加速器APP工具

一刀工具箱APP提供一键可将手机上的视频倍速播放,可以调整视频倍速的加速器,调节视频的速度也就是调节视频的播放速度!一键可将手机上的视频倍速播放,可以调整视频倍速的加速器,调节视频的速度也就是调节视频的播放速度!视频倍速-在线调倍速的加速器-一刀工具箱APP。...

无涯教程 7555

堆排序

堆在逻辑结构上是顺序存储的完全二叉树,左孩子2i,右孩子2i+1,付结点是i/2。大根堆,根>左右。小根堆,左右>根。算法思想:建堆:比如构造大根堆,就是将所有的非叶子结点(编号

ehhbxe的博客 185

uniapp+萤石视频监控实战:解决ezuikit.js真机调试不显示的5个关键步骤

本文针对Uniapp集成萤石视频监控时ezuikit.js在真机调试中黑屏不显示的问题,提供了5个关键解决步骤。核心方案是采用Webview加载独立H5播放页,以规避跨平台环境差异,并详细阐述了资源放置、多端适配、通信处理及系统化排查方法,确保视频流稳定播放。

weixin_29001655的博客 286

【算法&数据结构体系篇class06】:堆、大根堆、小根堆、优先队列

小根堆排序、优先队列:题目中提到了一个,每个元素移动的距离一定不超过k,那么就说明,从第一个数开始,前k+1个数里面,存在一个数,是一定要排在0位置的,这样才能使得移动不超过k个, 比如一个数组最小是1,长度为8,k=5,最小1是需要排在索引0位置的,为了满足移动不超过5个位置,那么在arr[0-k]区间内必然有1,最远只能在rr[k],那么也是移动k为来到0 k-k=0 ,利用这个特性,堆的最大值和堆末尾的值交换,然后减少堆的大小之后,再去调整堆,一直周而复始,时间复杂度为O(N*logN)

studyday1的博客 2395

流媒体学习之路(mediasoup)——simulcast 与 svc 简介(7)

流媒体学习之路(mediasoup)——simulcast 与 svc(7) 文章目录流媒体学习之路(mediasoup)——simulcast 与 svc(7)

qw225967的博客 7339

金融风控实战:用Python从零搭建贷款违约预测模型(附完整数据集)

本文详细介绍了如何使用Python从零构建金融风控中的贷款违约预测模型,涵盖数据清洗、特征工程、模型构建与评估等全流程。通过实战案例展示逻辑回归、XGBoost和LightGBM三大算法的对比,特别强调AUC-ROC指标在金融风控中的重要性,并附完整数据集和代码实现。

weixin_29175469的博客 238

前端人别慌:搞懂堆数据结构,面试手撕算法不再翻车(附实战技巧)

新礼物金额比堆顶小直接扔掉,大就替换,复杂度 O(log 10) ≈ 常数,60 FPS 稳稳的。别急着啃 C++,先把上面 TS 堆抄一遍,再去看源码,你会发出“哦,原来如此”的猪叫。微服务时代,N 台机器各自打日志,前端下载了 K 个文件,要按时间戳合并成一条时间线。直接甩代码,前端同学别慌,全是 TypeScript,浏览器里就能跑。标记,弹出时检查,遇到就丢弃,继续 pop,均摊仍 log n。吾辈才疏学浅,摹写之作,恐有瑕疵。建议先倒杯快乐水,找个安静角落,慢慢看,慢慢抄,慢慢笑。

一个做过前端开发的产品经理,经历过睿智产品的折磨导致脱发之后,励志要翻身"农奴"把歌唱,一边打入敌人内部一边持续提升自己,为我们广大开发同胞谋福祉,坚决抵制睿智产品折磨我们码农兄弟! 713

射频测试基础知识总结

表示可以辐射到空间的电磁频率,频率范围从300KHz~110GHz之间,射频简称RF,是高频交流变化电磁波的简称,其每秒变化小于1000次被称为低频电流,超过10000次的称为高频电流,而射频就是这种高频电流。为了确保天线接收的信号能够在接收机的最后一级被正确的恢复,一个好的低噪音放大器需要在放大信号的同时产生尽可能低的噪音以及失真。两种,带内试验的范围也有一定的差别,比如,带内试验主要是检测信号的质量,如功率、频谱宽度、调制质量,而带外测试的是信号的杂散、谐波,主要是看对频带之外的干扰有多大。

cny70的博客 9628

【JavaScript】堆(Heap)与优先队列实战:从原理到LeetCode解题

本文深入探讨了JavaScript中堆(Heap)与优先队列(Priority Queue)的原理与实践,通过超市排队的现实比喻解释其核心概念,并详细介绍了`datastructures-js/priority-queue`库的使用方法。文章结合LeetCode高频题型(如Top K问题、合并有序链表)提供实战代码示例,并分享性能优化技巧与工程实践案例,帮助开发者高效处理动态数据流和复杂调度场景。

blue的专栏 582

多目标跟踪(MOT)中的卡尔曼滤波(Kalman filter)和匈牙利(Hungarian)算法详解

多目标跟踪(MOT)中的卡尔曼滤波(Kalman filter)和匈牙利(Hungarian)算法详解 1. 概览 在开始具体讨论卡尔曼滤波和匈牙利算法之前,首先我们来看一下基于检测的目标跟踪算法的大致流程。 2. 卡尔曼滤波(Kalman filter) 目标跟踪中使用的就是最基础的 Kalman filter 算法。这里也仅仅讨论最基础的 Kalman filter 算法。 卡尔曼滤波算法的过程很简单,如下图所示。最核心的两个步骤就是预测和更新(下图的 correct)。 在目标跟踪任务中,目标的

生命在于折腾! 2万+

IDM 的免费替代品来了!这款开源下载器速度提升500%

💡分享一款开源的下载管理工具,支持多线程加速(最高提升500%)、队列管理、计划任务和浏览器集成,界面现代化且支持深色模式,跨平台支持Windows/Linux,是IDM的优秀替代方案🎈

XiaoqiangClub的博客 730

大根堆与小根堆的理解,如何手写一个堆,以及什么时候用自己手写的堆,什么时候用语言提供堆的api,(二者的区别)

大根堆与小根堆的理解,如何手写一个堆,以及什么时候用自己手写的堆,什么时候用语言提供堆的api,(二者的区别) 定义 Heap是一种数据结构具有以下的特点: 1)完全二叉树; 2)heap中存储的值是偏序; Min-heap: 父节点的值小于或等于子节点的值; Max-heap: 父节点的值大于或等于子节点的值; 用通俗语言来说,大根堆就是每个最大的数字在每个子树的最上方,及大根堆pop值为最大值,小根堆反之 堆的存储 堆的存储一般由数组表示,由于堆的实质就是完全二叉树,所以对于每个i来说(从0开始),左

weixin_44213940的博客 3929

Jenkins自动化部署服务到Kubernetes环境

通过Jenkins实现自动化部署可以大大提高软件交付的效率和质量。本文介绍的部署流程涵盖了从代码编译、Maven依赖管理、Docker镜像构建到Kubernetes部署的完整流程,并提供了通知机制以便及时了解部署状态。特别需要注意的是Maven与私服的配置,这是确保构建过程能够正常访问依赖包的关键。通过Jenkins的凭据管理功能,可以安全地管理私服的认证信息,避免敏感信息泄露。在实际应用中,您可能需要根据具体的项目需求和环境特点调整部署脚本。

探索云原生与智能化驱动下的安全运维新范式。关注DevSecOps、可观测性、AIOps等前沿领域,与您共赴技术前沿。 528

STL堆与手写堆

堆 堆的特点 插入一个数; 求集合中的最小值; 删除最小值; 以上是堆的最基本的特性,C++ STL 实现的小根堆支持上述操作。 删除任意一个元素; 修改如意一个元素; 以上两个特性 STL 堆无法直接实现,但是可以间接实现。 堆是一个完全二叉树。 以小根堆为例子,每个节点的值都小于等于两个子节点。所以根节点是集合的最小值。 STL 堆 STL 堆就是 优先队列。并且实现的堆是 小根堆。 定义: #include <queue> typedef pair<int, int>

qq_44960253的博客 581

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

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

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

堆(手写堆包含STL)

堆是什么,堆就像是一个金字塔,最顶端的是最值(最大值和最小值),堆其实就是一个二叉树,将最值元素放到根节点。子节点要么都小于父节点,要么都大于父节点。但是写手堆的话,我们用的是数组来存储,所以堆通常也被看做一颗树的数组对象。

qq_46056407的博客 3061

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

【C++语法】手写堆与有关堆的容器与函数

本文介绍了C++中堆的实现方法及相关容器函数。主要内容包括:1)手写堆的实现,详细讲解了构建、插入、删除和获取堆顶操作;2)标准库中的优先队列priority_queue,说明其定义方法、比较器使用及基本操作;3)算法库中与堆相关的函数,如make_heap、push_heap等。文章通过代码示例展示了如何高效实现堆结构,并比较了不同实现方式的性能特点,为C++开发者提供了堆相关操作的实用指南。

2401_85898378的博客 1118

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Java手写堆实现

poll方法是从堆顶移除一个元素,所以移除之后也要调整,堆是基于数组的,和末尾元素交换就行了,之后再向下调整。java的优先队列底层也是数组,每次调用offer()方法插入一个元素之后,要对堆进行重新调整,关键函数是。堆只是保证了堆顶的原始是整个堆中最大的或最小的,并不能保证层序遍历得到的序列是有序的。小根堆可以看到堆顶元素是最小的,每颗子树的根节点都是该树所有元素中最小的。堆中插入元素之后,在对应的位置需要up。,他的底层实现就是堆,常见的操作有。的堆叫做最大堆或大根堆,的堆叫做最小堆或小根堆。

2301_80121378的博客 1220

手写堆

堆 1.定义 堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。 2.性质 1.堆中某个节点的值总是不大于或不小于其父节点的值; 2.堆总是一棵完全二叉树。 将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。 堆是非线性数据结构,相当于一维数组,有两个直接后继。 3.应用思路(手写堆)...

aqg41577的博客 523

数据结构:堆手写

部分目录手写堆手写堆的存储手写堆的两个基本操作插入节点的原理求当前堆的最小值删除堆顶(最小值)删除任意一个元素手写堆的初始化板子:手写堆(我的) 手写堆 堆: 堆中某个结点的值总是不大于或不小于其父结点的值; 堆总是一棵完全二叉树。 完全二叉树:如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。 若将和此次序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于

出尘的博客 334

【堆 - 专题】系统已经提供了“堆”,为什么还要手写?

系统提供的“堆”不能用了?手写“加强堆”!

weixin_46879314的博客 1149

堆(手写小根堆)

若一棵二叉树至多只有最下面两层的结点的度数可以小于2,并且最下层的结点都集中在该层最左边的若干位置上,则此二叉树为完全二叉树。将节点上(up函数)下(down函数)移动,保证每个节点都小于等于左、右儿子,根节点为整个数据结构的最小值。此外,操作down()和up()都跟堆的层数有管,故这两种操作的时间复杂度都为O(logn)。(1)小根堆:每个点都小于等于左、右儿子,根节点为整个数据结构的最小值。(2)大根堆:每个点都大于等于左、右儿子,根节点为整个数据结构的最大值。第二行包含 n 个整数,表示整数数列。

m0_74381212的博客 1176

手写堆操作

手写堆操作 1. 插入一个数: heap[++ size] = x, up(size) 2. 求集合当中的最小值, heap[1] 3. 删除最小值, heap[1] = heap[size], size --, down(1) 4. 删除任意元素, heap[k] = heap[size], size --, down(k), up(k) 5. 修改任意元素, heap[k] = x, down(k), up(x) 基本操作 void down(int u){ int t = u; if(

water lover的博客 136

前端面试常见手写代码题【详细篇】

在前端面试中,经常会遇到防抖 、节流、函数柯里化、函数组合、instanceof 实现、实现new操作符的行为、深拷贝、继承实现:、手写Promise、数组中常见函数的实现等代码手写题,本文都已全部列举

前端探索者 3148

数据结构:手写堆

堆(heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质: 1.堆中某个节点的值总是不大于或不小于其父节点的值; 2.堆总是一棵完全二叉树。 手写堆用一维数组来储存数据,本篇以小根堆(某个节点总是大于其父节点)为例。 如果一个根节点的下标为x,则其左子节点的下表为2x,右子节点的下标为2x+1。 堆的基础操作可以用down和up两个操作来完成 1.插入一个数。 2.求集合当中的最小值。 3.删除最小值 4.删除任意一个元素。 ..

yaozizhi_yang的博客 1631

堆排列~~手写堆

堆 简单来说堆就是维护一个数据集合,堆的实质是一个二叉树; 堆的性质:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。 附上图 嘿嘿~: 今天我们说的小顶堆的堆排列介个问题(我才不会告诉你们我只学了小顶堆~小声bb)~~ 储存问题 (这里说一下,因为我们这次是手写堆的教程,跟STL中堆有所不同,4、5操作在STL中是无法完成...

kuaichongya的博客 416

[堆] 手写一个最小堆练习

之前面试的问题被问到了这个,一脸懵逼。毕竟系统库还挺好用的……因此刚刚花了点时间忙写了一个作为练习(最小堆),没有做越界判断。 struct heap { vector<int> data; int cur = 0; heap(int n) { ...

ayzejx8547408的博客 152
上一篇: 嵌入式软件和C/C++面经汇总
下一篇: C/C++中的STL
昊月光华
博客等级 码龄6年 340粉丝 158原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值