算法笔记p335堆

目录

    • 定义堆
    • 建堆(以大顶堆为例)
    • 删除堆顶元素
    • 插入元素
  • 堆排序
    • 排序思路
    • 代码实现

堆是一颗完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子结点的值。

  • 大顶堆:父亲结点的值大于或等于孩子结点的值。
  • 小顶堆:父亲结点的值小于或等于孩子结点的值。

定义堆

  • 使用数组来存储完全二叉树,结点按层序存储于数组中,其中第一个结点将存储于数组中的1号位,并且数组 i 号位表示的结点的左孩子就是 2i 号位,而右孩子则是(2i+1)号位。
#define MaxSize 1000
// heap为堆,n为元素个数
int heap[MaxSize], n = 10;

建堆(以大顶堆为例)

对一个给定的初始序列,用向下调整的思路构建大顶堆:

  1. 总是将当前结点V与它的左右孩子比较(如果有的话)。
  2. 假如孩子中存在权值比结点V的权值大的,就将其中权值最大的那个孩子结点与结点V交换。
  3. 交换完毕后继续让结点V和孩子比较,直到结点V的孩子的权值都比结点V的权值小或是结点V不存在孩子结点。
void swap(int *a, int *b) {
    int t = *a;
    *a = *b;
    *b = t;
}

// 对heap数组在[low,high]范围进行向下调整
// 其中low为欲调整结点的数组下标,high一般为堆的最后一个元素的数组下标
void downAdjust(int low, int high) {
    int i = low, j = i * 2;             // i为欲调整结点,j为其左孩子
    while (j <= high) {                 // 存在孩子结点
        // 如果右孩子存在,且右孩子的值大于左孩子
        if (j + 1 <= high && heap[j + 1] > heap[j])
            j = j + 1;      // 让j存储右孩子下标
        // 如果孩子中最大的权值比欲调整结点i大
        if (heap[j] > heap[i]) {
            swap(&heap[j], &heap[i]);   // 交换最大权值的孩子与欲调整结点
            i = j;                      // 保持i为欲调整结点
            j = i * 2;                  // j为i的左孩子
        } else
            break;                      // 孩子的权值均比欲调整结点i小,则无需向下调整
    }
}
  • 假设序列中元素的个数为n,由于完全二叉树的叶子结点个数为ceiling(n/2),因此数组下标在[1,floor(n/2)]范围内的结点都是非叶子结点。
  • 从floor(n/2)号位开始倒着枚举结点,对每个遍历到的结点i进行[i,n]范围的调整
  • 这样每次调整完一个结点后,当前子树中权值最大的结点就会处在根结点的位置,保证了每个结点都是以其为根结点的子树中的权值最大的结点

建堆代码如下,时间复杂度为O(n)。

// 建堆
void createHeap() {
    for (int i = n / 2; i >= 1; --i)
        downAdjust(i, n);
}

删除堆顶元素

删除堆顶元素,即删除堆中最大的元素(大顶堆),并让其仍然保持堆的结构。

  • 用最后一个元素覆盖堆顶元素。
  • 对根结点进行向下调整。

代码如下,时间复杂度为O(logn)。

// 删除堆顶元素
void deleteTop() {
    heap[1] = heap[n--];                // 用最后一个元素覆盖堆顶元素,并让元素个数减1
    downAdjust(1, n);               	// 向下调整堆顶元素
}

插入元素

向堆中插入一个元素,并让其仍然保持堆的结构。

  • 把要插入的元素放在数组的最后(也就是完全二叉树的最后一个结点后面)。
  • 然后进行向上调整操作:把欲调整结点与父亲结点比较,如果权值比父亲结点大,那么就交换其与父亲结点
  • 这样反复比较,直到到达堆顶或是父亲结点的权值较大为止。
  • 向上调整的时间复杂度为O(logn)。

代码如下。

// 对heap数组在[low,high]范围进行向上调整
// 其中low一般设置为1,high表示欲调整结点的数组下标
void upAdjust(int low, int high) {
    int i = high, j = i / 2;            // i为欲调整结点,j为其父亲结点
    while (j >= low) {                  // 父亲结点在[low,high]范围内
        // 父亲权值小于欲调整结点i的权值
        if (heap[j] < heap[i]) {
            swap(&heap[j], &heap[i]);   // 交换父亲结点和欲调整结点
            i = j;                      // 保持i为欲调整结点
            j = i / 2;                  // 保持j为i的父亲
        } else
            break;                      // 父亲的权值比欲调整结点i的权值大,调整结束
    }
}

// 添加元素x
void insert(int x) {
    heap[++n] = x;                      // 让元素个数加1,然后将数组末位赋值为x
    upAdjust(1, n);                 	// 向上调整新加入的结点n
}

堆排序

堆排序是指使用堆结构对一个序列进行排序。此处讨论大顶堆递增排序的情况。

排序思路

  1. 大顶堆建堆完毕后,堆顶元素是最大的。
  2. 取出堆顶元素,将堆的最后一个元素替换至堆顶。
  3. 针对堆顶元素,进行一次向下调整的操作。
  4. 重复②③,直至堆中只剩一个元素。
  5. 注意:
    1. 大顶堆排序完后,heap数组中的元素为升序;
    2. 小顶堆排序完后,heap数组中的元素为降序;
    3. 升序建大顶堆,降序建小顶堆

代码实现

  1. 倒着遍历数组(节省空间),访问到i号位时,将堆顶元素和i号位的元素交换。
  2. 接着在[1,i - 1]范围内对堆顶元素进行一次向下调整即可。
// 堆排序
void heapSort() {
    createHeap();                       // 建堆
    for (int i = n; i > 1; --i) {       // 倒着枚举,直到堆中只有一个元素
        swap(&heap[i], &heap[1]);       // 交换heap[i]与堆顶
        downAdjust(1, i - 1);       	// 调整堆顶
    }
}

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

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

相关文章

景联文科技:提供通用多模态数据,助力AI多模态领域实现飞跃式发展

回顾2023年&#xff0c;以ChatGPT为代表的通用人工智能大模型在全球范围内掀起了新一轮人工智能产业发展浪潮&#xff0c;我国人工智能大模型市场呈现百“模”争鸣、日新月异的迅猛发展态势。 根据大模型之家、钛媒体数据&#xff0c;2023年中国大模型市场规模达到147亿人民币&…

CMU 10-414/714: Deep Learning Systems --hw3

实现功能 在ndarray.py文件中完成一些python array操作 我们实现的NDArray底层存储就是一个一维向量&#xff0c;只不过会有一些额外的属性&#xff08;如shape、strides&#xff09;来表明这个flat array在维度上的分布。底层运算&#xff08;如加法、矩阵乘法&#xff09;都…

《优化接口设计的思路》系列:第九篇—用好缓存,让你的接口速度飞起来

一、前言 大家好&#xff01;我是sum墨&#xff0c;一个一线的底层码农&#xff0c;平时喜欢研究和思考一些技术相关的问题并整理成文&#xff0c;限于本人水平&#xff0c;如果文章和代码有表述不当之处&#xff0c;还请不吝赐教。 作为一名从业已达六年的老码农&#xff0c…

Android14音频进阶:AudioFlinger究竟如何混音?(六十三)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

开源离线语音识别输入工具CapsWriter v1.0——支持无限时长语音、音视频文件转录字幕。

分享一款开源离线语音识别输入工具&#xff0c;支持无限时长语音、音视频文件转录字幕。 软件简介&#xff1a; CapsWriter是一款免费开源且可完全离线识别的语音输入工具&#xff0c;无需担心因在线版本识别带来的各种隐私泄露问题。支持win7及以上的系统&#xff0c;已经更…

洛谷_P1104 生日_python写法

P1104 生日 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 知识点&#xff1a; 还是自定义规则的排序&#xff0c;然后这里还有python中如何在一行中输入多种类型的数据。 n int(input()) data [] num 1 for i in range(n):img list(input().split())s img[0]y int(img…

Axure RP10汉化版获取:低成本高效率操作!

作为市场份额最高的专业原型设计工具&#xff0c;Axure RP10 毫无疑问&#xff0c;功能的强大性和灵活性也受到许多产品经理和设计师的青睐。许多世界百强公司也在使用Axure进行原型设计 RP10。但对于许多本土设计师来说&#xff0c;Axure RP10 全英语界面和陡峭的学习曲线让人…

图解CodeWhisperer的安装使用

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! ​ 目录 &#x1f4d8; CodeWhisperer简介 &#…

CCIE-04-Layer2_WAN_TS

目录 实验条件网络拓朴 路由器配置开始排错&#xff0c; 要求R11可以访问R17的telnet检查R12和R11的e0/0口&#xff0c;有发现检查R17和R12的S4/0口&#xff0c; 有发现ping R17环回口地址&#xff0c;发现不通telnet R17环回口IP 实验条件 网络拓朴 路由器配置 R11 4组以太网…

qt-pdf-viewer-library 编译过程记录

1.qtpdfviewerinitializer.h 中 类模板问题需要修改为下面代码: https://github.com/develtar/qt-pdf-viewer-library 下载代码&#xff1a; 编译出现错误 修改代码&#xff0c;如下: 2.无法触发onViewerLoaded 事件&#xff0c;就是界面无法显示PDF文件 修改下面代码&#…

【技巧】ChatGPT Prompt 提示语大全

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 主要来自&#xff1a;https://github.com/f/awesome-chatgpt-prompts ChatGPT SEO prompts ChatGPT SEO提示 Contributed by: StoryChief AI Reference: 7 Powerful ChatGPT Prompts to Create SEO Content Faste…

RabbitMQ问题

如何实现顺序消费&#xff1f; 消息放入到同一个队列中消费 如何解决消息不丢失&#xff1f; 方案&#xff1a; 如上图&#xff1a;消息丢失有三种情况&#xff0c;解决了以上三种情况就解决了丢失的问题 1、丢失1--->消息在到达交换机的时候&#xff1b;解决&#xff1…

RabbitMQ 安装保姆级教程

目录 1.MQ引言 1.1 什么是MQ 1.2 MQ有哪些 1.3 不同MQ特点 2.RabbitMQ 的引言 2.1 RabbitMQ 2.2 RabbitMQ 的安装 2.2.1 下载 2.2.2 下载的安装包 2.2.3 安装步骤 3. RabiitMQ 配置 3.1RabbitMQ 管理命令行 3.2 web管理界面介绍 3.2.1 overview概览 3.2.2 Admin用…

整型数组按个位值排序 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 给定一个非空数组(列表)&#xff0c;其元素数据类型为整型&#xff0c;请按照数组元素十进制最低位从小到大进行排序&#xff0c;十进制最低位相同的元素&#xf…

wireshark windows 抓包https

windows下 1.配置环境变量以生成ssl协商会话密钥日志记录 系统设置-》高级设置-》环境变量 新增环境变量 SSLKEYLOGFILE C:\Users\Public\Documents\SSLKEY\sslkey.log 打开公用共享文档创建SSLKEY文件夹用于后续系统存放协商密钥日志 2.配置Wireshark选项进行抓包 点击…

计算机二级(Python)真题讲解每日一题:《方菱形》

描述‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬ 请写代码替换横线&#xff0…

【2024最新版,redis7】redis底层的10种数据结构

前言&#xff1a;本文redis版本&#xff1a;7.2.4 本文语雀原文地址&#xff08;首发更新&#xff09;&#xff1a;https://www.yuque.com/wzzz/redis/xg2cp37kx1s4726y 本文CSDN转载地址&#xff1a; https://blog.csdn.net/u013625306/article/details/136842107 1. 常见的数…

.htaccess全站设置SSL,wordpress全站设置SSL,网站重定向的次数过多”错误最佳解决方法教程

.htaccess全站设置SSL,wordpress全站设置SSL&#xff0c;网站重定向的次数过多”错误最佳解决方法教程 网上找了很多教程网无效**.htacces**设置&#xff0c;访问后台出现重定向次数过多&#xff0c;导致无法访问 找了好久&#xff0c;测试用AI机器人无法解决&#xff0c;参考…

【Linux】详谈进程优先级进程调度与切换

一、进程优先级 1.1、为什么要有优先级 进程要访问某种资源&#xff0c;进程通过一定的方式排队&#xff0c;确认享受资源的优先顺序。计算机中资源过少&#xff0c;所以进程访问某种资源时需要排队。 1.2、优先级的具体表示 进程的优先级其实就是PCB中的一个整形变量…

python失物招领系统-安卓-flask-django-nodejs-php

对于本失物招领 的设计来说&#xff0c; 它是应用mysql数据库、安卓等技术动态编程以及数据库进行努力学习和大量实践&#xff0c;并运用到了 建设中在整个系统的设计当中&#xff0c;具体根据网上失物招领的现状来进行开发的&#xff0c;具体根据用户需求实现网上失物招领网络…
最新文章