数据结构—堆(完全解析)

news2024/11/24 3:05:51

数据结构—堆(完全解析)

数据结构——堆(Heap)大根堆、小根堆

详解数据结构——堆

堆的基本存储

【从堆的定义到优先队列、堆排序】 10分钟看懂必考的数据结构——堆

【堆/排序】堆排序的两种建堆方法

【算法】排序算法之堆排序

C++:浅析STL之priority_queue构建大根堆与小根堆

基本概念

堆通常是一个可以被看做一棵完全二叉树的数组对象

堆满足下列性质:

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

Min-heap(大根堆): 父节点的值小于或等于子节点的值

Max-heap(小根堆): 父节点的值大于或等于子节点的值
在这里插入图片描述

堆的存储

一般都用数组来表示堆,i结点的父结点下标就为(i–1)/2

它的左右子结点下标分别为2 * i + 1和2 * i + 2

如第0个结点左右子结点下标分别为1和2

在这里插入图片描述

堆的插入和上浮

  • 当一个新元素想要插入这个堆的时候,我们首先把他放到这个堆的末尾
  • 然后依据堆的特性,对它的位置进行调整,由于要保持父结点的值要永远少于其子节点的值,而2的直接父节点6大于了它,所以要把他们两的位置对换
  • 对换完毕后,再检查这个堆的状态,发现其父节点3仍然大于自己,所以继续往上和3对换
  • 结束后和0比较,0不大于自己,所以停留在原地不动,插入结束
  • 简单来说,插入一个结点就是将该元素插入到堆的尾部,然后不断上浮调整位置,直至满足堆的条件

在这里插入图片描述

堆的删除和下沉

  • 删除一般指的都是删除堆顶元素,在堆顶元素被拿掉后,将末尾元素置换上来,进行下沉操作
  • 由于这是最小堆,堆顶一定是最小元素,首先6大于左结点1,需要下沉,
  • 下沉完以后继续和它子节点比较,发现左结点2小于自身,继续下沉
  • 最后89都比6大,停止下沉。
  • 总结来说,意思就是删除堆顶元素后,用末尾元素补上,然后不断下沉,直至满足堆的条件

在这里插入图片描述

堆的建立

自顶向下,时间复杂度为O(nlogn)

在这里插入图片描述
自下而上,时间复杂度为O(n)

从倒数第二排开始,对每一个父节点进行下滤操作,直到根节点操作完毕

在这里插入图片描述
在这里插入图片描述

堆的应用

优先队列

优先队列有两个操作,插入队列和弹出最小元素

在这里插入图片描述

优先队列利用小根堆实现,弹出根节点即可实现弹出最小元素的操作

在这里插入图片描述

弹出后要将剩余的元素调整为堆,将最后一个元素放到根节点,进行下沉操作即可

在这里插入图片描述
在这里插入图片描述

堆排序

  • 先把数组构造成一个大顶堆(父亲节点大于其子节点),然后把堆顶(数组最大值,数组第一个元素)和数组最后一个元素交换,这样就把最大值放到了数组最后边
  • 把数组度-1,再进行构造堆把剩余的第二大值放到堆顶,输出堆顶(放到剩余未排序数组最后面),依次类推,直至数组排序完成
#include <iostream>
#include <algorithm>
using namespace std;
void max_heapify(int arr[], int start, int end) {
    //建立父节点指标和子节点指标
    int dad = start;
    int son = dad * 2 + 1;
    while (son <= end) { //若子节点指标在范围内才做比较
        if (son + 1 <= end && arr[son] < arr[son + 1]) //先比较两个子节点大小,选择最大的
            son++;
        if (arr[dad] > arr[son]) //如果父节点大于子节点代表调整完毕,直接跳出函数
            return;
        else { //否则交换父子内容再继续子节点和孙节点比较
            swap(arr[dad], arr[son]);
            dad = son;
            son = dad * 2 + 1;
        }
    }
}
void heap_sort(int arr[], int len) {
    //初始化,i从最后一个父节点开始调整
    for (int i = len / 2 - 1; i >= 0; i--)
        max_heapify(arr, i, len - 1);
    //先将第一个元素和已经排好的元素前一位做交换,再从新调整(刚调整的元素之前的元素),直到排序完毕
    for (int i = len - 1; i > 0; i--) {
        swap(arr[0], arr[i]);
        max_heapify(arr, 0, i - 1);
    }
}
int main() {
    int arr[] = { 3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6 };
    int len = (int) sizeof(arr) / sizeof(*arr);
    heap_sort(arr, len);
    for (int i = 0; i < len; i++)
        cout << arr[i] << ' ';
    cout << endl;
    return 0;
}

C++ STL大根堆小根堆

在C++中优先队列默认的是大根堆,如果用小根堆则加入greater

#include <queue>
priority_queue<int, vector<int>>s;//大根堆
priority_queue<int, vector<int>, less<int>>s;//less表示按照递减(从大到小)的顺序插入元素,大根堆
priority_queue<int, vector<int>, greater<int>>s;//greater表示按照递增(从小到大)的顺序插入元素,小根堆

支持的顺序容器:vector,queue,默认是vector

priority_queue类能按照有序的方式在底层数据结构中执行插入、删除操作

q.pop();//删除优先队列priority_queuel的最高优先级元素(通过调用底层容器的pop_back()实现)
q.push(item);//在priority._queue优先级顺序合适的位置添加创建一个值为item的元素(通过调用底层容器的push_back()操作实现)
q.emplace(args);//在priority_queue优先级顺序合适的位置添加个由args构造的元素(通过调用底层容器的emplace_back()操作实现)
q.top();//返回priority_queue的首元素的引用(通过调用底层容器的front()操作实现)
q.empty();//判断q是否为空,空返回true,否则返回false(通过调用底层容器的empty()操作实现)
q.size();//返回q中的元素个数(通过调用底层容器的size()操作实现)
swap(q,p);//交换两个优先队列priority_queue p,q的内容,p和q的底层容器类型也必须相同(通过调用底层容器的swap0操纵实现)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Tips】通过背数据了解业务

学习资料&#xff1a;做了三年数据分析&#xff0c;给你的几点建议 1. 通过背数据了解业务 原文&#xff1a; 总结&#xff1a; 方法&#xff1a;每天早上去到公司第一件事情就是先背一遍最新的各种指标。原理&#xff1a; 数据敏感性就是建立在对数据的了解和熟悉上。业务的…

使用Autoware标定工具包联合标定相机和激光雷达

前面文章介绍了&#xff0c;安装autoware标定工具包、ros驱动usb相机、robosense-16线激光雷达的使用&#xff0c;本文记录使用Autoware标定工具包联合标定相机和激光雷达的过程。1.ros驱动相机&#xff0c;启动相机&#xff1b;启动激光雷达2.联合录制bag包rosbag record -a 参…

由浅入深了解超文本传输协议http

什么是超文本传输协议&#xff1f; 超文本传输协议&#xff08;英语&#xff1a;HyperText Transfer Protocol&#xff0c;缩写&#xff1a;HTTP&#xff09;是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP是万维网的数据通信的基础。 通过HTTP或HTTPS协议请求…

8年测开经验面试28K公司后,吐血整理出1000道高频面试题和答案

1、python的数据类型有哪些 答&#xff1a;Python基本数据类型一般分为&#xff1a;数字、字符串、列表、元组、字典、集合这六种基本数据类型。 浮点型、复数类型、布尔型(布尔型就是只有两个值的整型)、这几种数字类型。列表、元组、字符串都是序列。 2、列表和元组的区别 答…

postgresql 数据库 主从切换 测试

postgresql 数据库 主从切换 测试 文章目录postgresql 数据库 主从切换 测试前言环境&#xff1a;主从切换1. 查看数据库状态&#xff1a;2. 备库切换主库3. 旧主库切换成备库&#xff1b;4 查看状态后记前言 因数据库等保需要&#xff0c;需要对老系统的数据库进行主从切换来…

【企业云端全栈开发实践-2】Spring Boot Controller

本节目录一、Web入门二、控制器1、Controller2、RestController3、路由映射4、Method匹配5、参数传递6、entity实体层一、Web入门 Spring Boot将传统Web开发的mvc、json、tomacat等框架整合&#xff0c;提供了spring-boot-starter-web组件&#xff0c;简化了Web的应用配置。 …

一条推送的背后运营逻辑

每天我们的手机都收到大量信息&#xff0c;大多来自各APP的推送。每收到一条推送&#xff0c;不只是收到了一串简单的文字&#xff0c;背后还有一系列的隐藏逻辑。几年前我也做过“推送背后的女人”……&#xff08;其实就是干过APP消息推送运营啦~^^~&#xff09;今天就来分享…

【Java 面试合集】String, StringBuffer和StringBuilder 之间的不同

String&#xff0c; StringBuffer和StringBuilder 之间的不同 1. 概述 嗨&#xff0c;大家好【Java 面试合集】又来了&#xff0c;今天我们分享的主题是String&#xff0c; StringBuffer和StringBuilder 之间的不同。 大家别看这个知识点不难&#xff0c;但是里面的细知识很多…

利用Python实现局部异常因子(LOF)的计算

1 LOF算法 局部异常因子(Local Outlier Factor&#xff0c;LOF)算法是目前比较常用的离群点检测算法&#xff0c;该算法通过一种模糊的手段来判断数据对象是否为异常点。 对象ppp的kkk距离&#xff1a;在数据集DDD中&#xff0c;将对象ppp与距其第kkk远的对象ooo之间的距离定义…

(二十四)、实现评论功能(4)【uniapp+uinicloud多用户社区博客实战项目(完整开发文档-从零到完整项目)】

1&#xff0c;创建reply回复页面 1.1 在comment-item子组件中添加click <view class"comment-item" click"goReply">1.2 methods中添加点击跳转回复页面的方法 //跳转去回复页面goReply() {uni.navigateTo({url: "/pages/reply/reply"})}…

Linux 基础知识之权限管理

目录一、权限的认识二、用户切换三、文件权限1.三类文件访问者2.文件权限类型3.文件访问权限4.文件权限值表示一、权限的认识 权限是对用户所能进行的操作的限制&#xff0c;如果不对用户作出限制&#xff0c;那么碰到恶意用户&#xff0c;就会损害其他用户的利益。 Linux是多用…

最新文件快递柜系统网站源码-Fastapi+Sqlite3+Vue2+ElementUI-简洁好用

## 主要特色 - [x] 轻量简洁:Fastapi+Sqlite3+Vue2+ElementUI - [x] 轻松上传:复制粘贴,拖拽选择 - [x] 多种类型:文本,文件 - [x] 防止爆破:错误次数限制 - [x] 防止滥用:IP限制上传次数 - [x] 口令分享:随机口令,存取文件,自定义次数以及有效期 - [x] 匿名分享:无…

机器学习算法竞赛实战:如何看到机器学习竞赛问题?

机器学习算法竞赛实战-竞赛问题建模 更新《机器学习算法竞赛实战》一书的阅读笔记&#xff0c;更多详细的内容请阅读原书。本文的主要内容包含&#xff1a; 竞赛问题的3个主要部分-如何理解竞赛问题机器学习的样本选择如何线下评估模型实战案例 公众号&#xff1a;尤而小屋作…

scheduling Request(SR)

欢迎关注同名微信公众号“modem协议笔记”。 UE上报BSR&#xff0c;期望网络参照BSR&#xff0c;下发UL grant给UE以便发送UL data&#xff0c;正常情况下&#xff0c;整个过程都会比较顺利。但是世事难料&#xff0c;网络难免有自己的小脾气或者发送BSR不太顺畅&#xff0c;导…

通过Buildroot自制根文件系统

前言根文件系统是Linux内核启动之后读取的一个文件系统&#xff0c;并从这个文件系统中加载第一个init应用程序并启动&#xff0c;就是Linux上俗称的root进程、根进程制作它的方式有很多&#xff0c;例如busybox、yocto&#xff0c;但是这两个方式有缺点&#xff0c;第一个是bu…

JVM级别内存屏障如何禁止指令重排序的

承接上文证明CPU指令是乱序执行的当多个cpu访问同一份数据的时候怎么保证数据的一致性&#xff1f;在最底层级别的控制有好多种&#xff1a;第一种叫关中断&#xff0c;就是访问任何数据的时候必须有一个中断信号量的存在。很多传统的cpu就是靠它实现的&#xff0c;从内存读东西…

高速风筒的IPM模块解决方案

高速吹风筒是利用高转速产生的大风量来快速吹干头发&#xff0c;同时&#xff0c;高转速也使得电机与叶轮的体积缩小&#xff0c;便于设计出灵巧便携的外形。12万转的高速风筒的整体解决方案&#xff0c;满足高速吹风筒的所有应用场景&#xff0c;让客户用芯能的功率器件能更快…

PMP认证的PDU是什么?

PDU&#xff08;Professional Development Units&#xff09;即专业发展单元&#xff0c;是指您获取认证后&#xff0c;就项目管理专业进行学习、授课、或提供志愿服务的累积时间&#xff0c;以小时为单位&#xff0c;1小时即累积1个PDU。自证书获取日起&#xff0c;以三年为A周…

Ansible 多机自动化工具 初学笔记

此文档仅张聪明同学个人笔记&#xff1b;新负责KTH-RPL Cluster GPU的漫漫学习长路 English Docs: official https://docs.ansible.com/ansible/latest/index.html 中文相关文档&#xff1a; https://ansible.leops.cn/basic/Quickstart/https://blog.csdn.net/xinshuzhan/a…

java基础学习 day44(多态的优点和劣势)

1. 多态的优势 在多态形式下&#xff0c;右边对象可以实现解耦合&#xff08;即之后的代码与右边的子类对象不绑定&#xff0c;在更改子类对象后&#xff0c;之后的代码仍可以使用&#xff09;&#xff0c;便于扩展和维护在定义方法的时候&#xff0c;使用父类型作为参数&…