算法学习系列(十五):最小堆、堆排序

目录

  • 引言
  • 一、最小堆概念
  • 二、堆排序模板(最小堆)
  • 三、模拟堆

引言

这个堆排序的话,考的还挺多的,主要是构建最小堆,并且在很多情况下某些东西还用得着它来优化,比如说迪杰斯特拉算法可以用最小堆优化,然后面试和考研用的也是挺多的,总之开始吧。

一、最小堆概念

本文只讲述最小堆,其一这个用的最多,而且跟最大堆来说其实都是差不多的,就一个小于一个大于

最小堆:首先是一个完全二叉树,然后每个结点都小于或等于其两个儿子,性质:根结点是整个堆的最小值。因为父亲是最小的,然后儿子又作为其儿子的父亲,也是其最小的,所以推出堆根是最小的。

存储方式:是用数组来存的,i 号下标的儿子为 2 * i,2 * i + 1,i 号下标的父亲为 i / 2
在这里插入图片描述

STL:优先级队列就是最小堆

二、堆排序模板(最小堆)

整体思路:先构建一个最小堆,然后输出堆根,再把堆根删了,再次构建,重复往返
删除堆根:用 h[size] 覆盖 h[1] ,size-- ,down(1)
这个模板我们用例题来说明

输入一个长度为 n 的整数数列,从小到大输出前 m 小的数。

输入格式
第一行包含整数 n 和 m。
第二行包含 n 个整数,表示整数数列。

输出格式
共一行,包含 m 个整数,表示整数数列中前 m 小的数。

数据范围
1≤m≤n≤105,1≤数列中元素≤109

输入样例:
5 3
4 5 1 3 2

输出样例:
1 2 3
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int N = 1e5+10;

int h[N];  //h[i]代表第堆中的i号下标对应的值
int n, m, cnt;  //cnt代表堆中的数量

//元素变小了,就up
void up(int u)
{
    while(u / 2 && h[u / 2] > h[u])  //若u>=1 并且比父亲大就交换,然后u变成父亲继续判断
    {
        swap(h[u], h[u/2]);
        u >>= 1;
    }
}

//元素变大了,就down
void down(int u)  //将下标为u的元素下移
{
    int t = u;
    if(u * 2 <= cnt && h[2 * u] < h[t]) t = 2 * u;  
    if(u * 2 + 1 <= cnt && h[2 * u + 1] < h[t]) t = 2 * u + 1;  //判断最小的值t
    
    if(t != u)  //若有一个儿子比自己小
    {
        swap(h[u], h[t]);  //交换值
        down(t);  //再次判断这个儿子
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) scanf("%d", &h[i]);
    cnt = n;
    
    for(int i = cnt / 2; i; --i) down(i);  //从倒数第二层的元素开始down到根,可以构建一个最小堆
    
    while(m--)
    {
        printf("%d ", h[1]);  //每次都是堆根的元素最小
        swap(h[1], h[cnt]);
        cnt--;
        down(1);
    }
    
    return 0;
}

在这里插入图片描述

三、模拟堆

我们还是用例题来说明
然后这个有一个要求就是要对第k个插入的元素进行操作,但是我们又不知道第k个元素是谁,只知道下标,所以得维护两个数组ph[i] ,hp[i],代表ph[k] == i,hp[i] == k,h[i] == a

维护一个集合,初始时集合为空,支持如下几种操作:
I x,插入一个数 x;
PM,输出当前集合中的最小值;
DM,删除当前集合中的最小值(数据保证此时的最小值唯一);
D k,删除第 k 个插入的数;
C k x,修改第 k 个插入的数,将其变为 x;

现在要进行 N 次操作,对于所有第 2 个操作,输出当前集合的最小值。

输入格式
第一行包含整数 N。
接下来 N 行,每行包含一个操作指令,操作指令为 I x,PM,DM,D k 或 C k x 中的一种。

输出格式
对于每个输出指令 PM,输出一个结果,表示当前集合中的最小值。每个结果占一行。

数据范围
1≤N≤105
−109≤x≤109
数据保证合法。

输入样例:
8
I -10
PM
I -10
D 1
C 2 8
I 6
PM
DM

输出样例:
-10
6
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int N = 1e5+10;

int h[N], hp[N], ph[N];
int n, cnt, idx;

void swap_heap(int a, int b)
{
    swap(ph[hp[a]],ph[hp[b]]);
    swap(hp[a],hp[b]);
    swap(h[a], h[b]);
}

void up(int u)
{
    while(u / 2 && h[u] < h[u / 2])
    {
        swap_heap(u, u/2);
        u >>= 1;
    }
}

void down(int u)
{
    int t = u;
    if(u * 2 <= cnt && h[u * 2] < h[t]) t = u * 2;
    if(u * 2 + 1 <= cnt && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
    
    if(t != u)
    {
        swap_heap(t,u);
        down(t);
    }
}

int main()
{
    scanf("%d", &n);
    
    while(n--)
    {
        char op[5];
        int k, x;
        
        scanf("%s", op);
        if(!strcmp(op,"I"))
        {
            scanf("%d", &x);
            cnt++, idx++;
            h[cnt] = x;
            hp[cnt] = idx, ph[idx] = cnt;
            up(cnt);
        }
        else if(!strcmp(op,"PM"))
        {
            printf("%d\n", h[1]);
        }
        else if(!strcmp(op,"DM"))
        {
            swap_heap(1,cnt);
            cnt--;
            down(1);
        }
        else if(!strcmp(op,"D"))
        {
            scanf("%d", &k);
            k = ph[k];
            swap_heap(k, cnt);
            cnt--;
            up(k);
            down(k);
        }
        else
        {
            scanf("%d%d", &k, &x);
            k = ph[k];
            h[k] = x;
            up(k);
            down(k);
        }
    }
    
    return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/276746.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Xamarin开发:商场促销(策略设计模式)

Xamarin开发:商场促销&#xff08;策略设计模式&#xff09; 一、介绍二、需求分析三、实现四、需求分析问题1解决方案问题2解决方案 五、增加新需求六、代码优化与分析总结 一、介绍 本文引用《大话设计模式》第二章节的内容进行学习分析&#xff0c;仅供学习使用 这里接着我…

Java设计模式-装饰者模式

目录 一、星巴克咖啡订单项目 二、装饰者模式 &#xff08;一&#xff09;定义 &#xff08;二&#xff09;原理 &#xff08;三&#xff09;装饰者模式解决星巴克咖啡订单 一、星巴克咖啡订单项目 星巴克咖啡订单项目&#xff08;咖啡馆&#xff09;&#xff1a; 1) 咖…

菜鸟学习vue3笔记-vue hooks初体验

import { ref } from "vue"; export default function () {let a1 ref(1);let a2 ref(5);let c ref(0);function add() {a1.value;a2.value;}return {add,a1,a2,c,}; }<template><div><p>第一个数字{{ a1 }}</p><p>第二个数字{{ a2…

java勤工助学信息管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web勤工助学信息管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境 为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为M…

Java线上问题排查思路

1、Java 服务常见问题 Java 服务的线上问题从系统表象来看大致可分成两大类: 系统环境异常、业务服务异常。 系统环境异常&#xff1a;主要从CPU、内存、磁盘、网络四个方面考虑。比如&#xff1a;CPU 占用率过高、CPU 上下文切换频率次数较高、系统可用内存长期处于较低值、…

K8s实战-基于LivenessProbe健康检查

LivenessProbe探针用于判断容器是否存活&#xff0c;如果探测到容器不健康&#xff0c;则kubelet将杀掉该容器&#xff0c;然后根据重启策略处理。 LivenessProbe的实现方式&#xff1a; ExecAction&#xff1a;在容器内部执行一个命令&#xff0c;如果该命令的返回码为0&…

计算机毕业设计 基于SpringBoot的高校危化试剂仓储管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

最短路径(数据结构实训)(难度系数100)

最短路径 描述&#xff1a; 已知一个城市的交通路线&#xff0c;经常要求从某一点出发到各地方的最短路径。例如有如下交通图&#xff1a; 则从A出发到各点的最短路径分别为&#xff1a; B&#xff1a;0 C&#xff1a;10 D&#xff1a;50 E&#xff1a;30 F&#xff1a;60 输…

白话机器学习的数学-1-回归

1、设置问题 投入的广告费越多&#xff0c;广告的点击量就越高&#xff0c;进而带来访问数的增加。 2、定义模型 定义一个函数&#xff1a;一次函数 y ax b &#xff08;a 是斜率、b 是截距&#xff09; 定义函数&#xff1a; 3、最小二乘法 例子&#xff1a; 用随便确定的参…

BDTC2023:CloudberryDB开源创新与实践

中国大数据技术大会&#xff08;BDTC&#xff09;由中国计算机学会&#xff08;CCF&#xff09;创立于2008年&#xff0c;已经成为国内外极具行业实践的专业大数据交流平台。12月22日-24日&#xff0c;第十七届中国大数据技术大会&#xff08;BDTC 2023&#xff09;在广州举行。…

文字识别技术在未来会有怎样的发展?

随着科技的不断发展&#xff0c;文字识别技术也在不断地改进和完善。未来&#xff0c;文字识别技术将会在更多的领域得到应用&#xff0c;并且将会更加智能化、高效化和个性化。 首先&#xff0c;随着深度学习技术的不断发展&#xff0c;文字识别技术将会更加智能化。目前&…

ubuntu22下安装minconda

bing 搜索 canda install 找到官方网站 https://docs.conda.io/projects/miniconda/en/latest/ 这里我们安装minconda。 官网有安装方法。 mkdir -p ~/miniconda3 wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh…

docker的基本管理和相关概念

docker的基本管理和概念 docker&#xff1a;开源的应用容器引擎。基于go语言开发的。运行在linux系统当中的开源的&#xff0c;轻量级的“虚拟机” docker的容器技术可以在一台主机上轻松的为任何应用创建一个轻量级的&#xff0c;可移植的&#xff0c;自给自足的容器 docke…

Java 读取超大excel文件

注意&#xff1a;此参考解决方案只是针对xlsx格式的excel文件&#xff01; Maven <dependency><groupId>com.monitorjbl</groupId><artifactId>xlsx-streamer</artifactId><version>2.2.0</version> </dependency>读取方式1…

Android画布Canvas矩阵Matrix放大裁剪Rect区域的Bitmap,Kotlin

Android画布Canvas矩阵Matrix放大裁剪Rect区域的Bitmap&#xff0c;Kotlin private fun mydraw() {val originBmp BitmapFactory.decodeResource(resources, R.mipmap.pic).copy(Bitmap.Config.ARGB_8888, true)val newBmp Bitmap.createBitmap(originBmp.width, originBmp.h…

爬虫基础一(持续更新)

爬虫概念&#xff1a; 通过编写程序&#xff0c;模拟浏览器上网&#xff0c;然后让其去互联网上抓取数据的过程 分类&#xff1a; 1&#xff0c;通用爬虫&#xff1a;抓取一整张页面数据 2&#xff0c;聚焦爬虫&#xff1a;抓取页面中的局部内容 3&#xff0c;增量式爬虫&…

CUMT--Java--线程

目录 一、线程 1、概述 2、Java线程模型 3、主线程 二、创建线程 1、继承Thread类 2、实现Runnable接口 3、使用Callable和Future接口 三、线程生命周期 1、新建和就绪状态 2、运行和阻塞状态 3、死亡状态 四、线程优先级 五、线程同步 1、非同步情况 2、同步…

浅谈WPF之控件模板Control Template和数据模板Data Template

WPF不仅支持传统的Windows Forms编程的用户界面和用户体验设计&#xff0c;同时还推出了以模板为核心的新一代设计理念。在WPF中&#xff0c;通过引入模板&#xff0c;将数据和算法的“内容”和“形式”进行解耦。模板主要分为两大类&#xff1a;数据模板【Data Template】和控…

创建加密分区或者文件

文章目录 [GParted 中已清除的分区与未格式化的分区](https://superuser.com/questions/706624/cleared-vs-unformatted-partition-in-gparted)创建加密分区解密创建的加密分区以便挂载格式化设备未具体的格式&#xff08;这里为ext4格式&#xff09;创建挂载点目录挂载加密的文…

java在线票务系统(选座)Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java servlet 在线票务系统&#xff08;选座&#xff09;管理系统是一套完善的java web信息管理系统 系统采用serlvetdaobean&#xff08;mvc模式)&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要…
最新文章