数据结构0基础学习堆

文章目录

  • 简介
  • 公式
  • 建立堆
    • 函数解释
  • 堆排序O(n logn)
  • topk问题

简介

堆是一种重要的数据结构,是一种完全二叉树,(二叉树的内容后面会出),
堆分为大小堆,大堆,左右结点都小于根节点,(又称子节点和父节点),
小堆则反过来,可以用静态数组/顺序表实现

公式

已知某节点下标 i ,(根节点下标为0),

  • 左孩子节点为 2*i+1
  • 右孩子节点为 2*i+2
  • 父节点 ( i - 1 )/ 2

建立堆

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int HPTypeDate;
typedef struct {HPTypeDate* a;HPTypeDate size;HPTypeDate capacity;
}HP;

将元素插入a里面,size表示堆里面的元素个数,避免浪费内存,满了就开辟

void HeapInit(HP* php);
void HeapPush(HP* php, HPTypeDate x);
void Adjustup(HPTypeDate* a, int child);
void swap(HPTypeDate* a, HPTypeDate* b);
void HeapPrint(HP* php, HPTypeDate n);
HPTypeDate HPTop(HP* php);
void HPPop(HP* php);
bool HPEmpty(HP* php);
void Adjustdown(HPTypeDate* a, HPTypeDate n,HPTypeDate parent);

堆常用的函数,初始化,插入,上下调整,取堆顶元素,消堆顶元素

函数解释

void HeapInit(HP* php)
{assert(php);php->a = (HPTypeDate*)malloc(sizeof(HPTypeDate) * 4);if (php->a == NULL){perror("malloc fail");return;}php->size = 0;php->capacity = 4;
}

初始化,为数组a开辟空间,size赋值,capacity先赋值4,

void HeapPrint(HP* php, HPTypeDate n)
{assert(php);for (int i = 0;i < n;i++){printf("%d ", php->a[i]);}printf("\n");
}
void swap(HPTypeDate* a, HPTypeDate* b)
{int p = *b;*b = *a;*a = p;
}

打印和交换函数

void Adjustup(HPTypeDate* a, int child)
{int parent = (child - 1) / 2;while (child > 0){if (a[child] < a[parent]){swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}elsebreak;}
}

向上调整函数,非常重要,传入child,是某个节点的下标。再找出父亲节点,判断孩子和父亲节点的大小,根据建大小堆的不同 if中判断符号作改变,我这里是小堆,再递归,父亲的位置给孩子,父亲根据公式 再重新向上找点,一直往复,直到不满足堆的规定时间复杂度为O(log n);

void Adjustdown(HPTypeDate* a,HPTypeDate n, HPTypeDate parent)
{HPTypeDate child = parent * 2+1;while (child < n){if (child+1<n&&a[child] < a[child + 1]){child = child + 1;}if (a[parent] > a[child]){swap(&a[parent], &a[child]);parent = child;child = parent * 2 + 1;}else break;}
}

向下调整,传入父节点下标,求出孩子结点,找出那个大孩子,再根据大小堆是否与孩子交换,递归,与向上类似时间复杂度与向上一致

void HeapPush(HP* php, HPTypeDate x)
{assert(php);if (php->capacity == php->size){HPTypeDate* tmp = (HPTypeDate*)realloc(php->a, sizeof(HPTypeDate) * (php->capacity) * 2);if (tmp == NULL){perror("realloc");return;}php->a = tmp;php->capacity *= 2;}php->a[php->size++] = x;Adjustup(php->a, php->size - 1);
}

插入函数,判断空间够不够,不够realloc再开辟capacity2的,把开辟的空间给a,capacity=2;
将新来的数插入数组末尾,再向上调整一遍。时间复杂度最坏O(n),均摊O(1)

bool HPEmpty(HP* php)
{return php->size == 0;
}
HPTypeDate HPTop(HP* php)
{assert(php);return php->a[0];
}
void HPPop(HP* php)
{assert(php);if (HPEmpty(php)) return;swap(&php->a[0], &php->a[php->size - 1]);php->size--;Adjustdown(php->a, php->size,0);
}

消去堆顶函数,将堆顶和堆尾交换,size-- 就行,再将堆顶向下调整

堆排序O(n logn)

#include <stdio.h>void swap(int* a, int* b)
{int p = *a;*a = *b;*b = p;
}
void Adjustdown(int* a, int parent, int n)
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child] < a[child + 1])child = child + 1;if (a[child] > a[parent]){swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else break;}}
void heap_sort(int* a, int n)
{for (int i = (n - 2) / 2;i >= 0;i--){Adjustdown(a, i, n);}int end = n - 1;while (end > 0){swap(&a[0], &a[end]);Adjustdown(a, 0, end);end--;}
}
int main()
{int a[] = { 1,9,8,5,6,4,7,4 };heap_sort(a, 8);for (int i = 0;i < 8;i++){printf("%d ", a[i]);}return 0;
}

先前向上调整函数参数为指针,可以直接用来排序,
先将数组建成一个大堆,从中间开始往下调整O(n),但从下向上调整O(nlogn)
默认升序,若想降序

  • 方法 1:改用 小根堆(最小堆),这样堆顶是最小值,交换到末尾后自然形成降序。

  • 方法 2:仍然用 大根堆,但 不交换堆顶到末尾,而是 直接输出堆顶(每次取最大值),但这样会破坏原数组

topk问题

给出一堆数让求最大的前k个,若给几十亿个数,开辟不了这么大的内存,所以要取巧,
建k个大小的小堆,遍历一遍数,若比堆顶大就代替堆顶,进堆,最后几个就是最大的

#include <stdio.h>void swap(int* a, int* b)
{int p = *a;*a = *b;*b = p;
}
void Adjustdown(int* a, int parent, int n)
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child] < a[child + 1])child = child + 1;if (a[child] < a[parent]){swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else break;}}
void heap_sort(int* a, int k)
{//建堆for (int i = (k - 2) / 2;i >= 0;i--){Adjustdown(a, i, k);}//n-k比较for(int i=k;i<8;i++){int val = a[i];if (val > a[0]){swap(&val, &a[0]);Adjustdown(a, 0, k);}}
}
int main()
{int a[] = { 1,9,8,5,6,4,7,4 };int k = 2;heap_sort(a, k);for (int i = 0;i < k;i++){printf("%d ", a[i]);}return 0;
}

代码稍微一改就行,要求前k小的就建大堆,若比堆顶小,代替进堆

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

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

相关文章

4.17--4.19刷题记录(贪心)

第一部分&#xff1a;准备工作 代码随想录中解释为&#xff1a;贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 而我的理解为&#xff1a;贪心实质上是具有最优子结构的一种算法。所有的解都能由当前最优的解组成。 第二部分&#xff1a;开始刷题 &…

学习笔记十七——Rust 支持面向对象编程吗?

&#x1f9e0; Rust 支持面向对象编程吗&#xff1f; Rust 是一门多范式语言&#xff0c;主要以 安全、并发、函数式、系统级编程为核心目标&#xff0c;但它同时也支持面向对象的一些关键特性&#xff0c;比如&#xff1a; 特性传统 OOP&#xff08;如 Java/C&#xff09;Ru…

【Linux】43.网络基础(2.5)

文章目录 2.4 TCP/UDP对比2.4.1 用UDP实现可靠传输(经典面试题) 2.5 TCP 相关实验2.5.1 理解 listen 的第二个参数 2.4 TCP/UDP对比 我们说了TCP是可靠连接, 那么是不是TCP一定就优于UDP呢? TCP和UDP之间的优点和缺点, 不能简单, 绝对的进行比较TCP用于可靠传输的情况, 应用于…

three.js与webgl在buffer上的对应关系

一、three.js的类名 最近开始接触three.js 看到three.js中的一些类名和webgl的很相似 不自觉的就想对比一下 二、three.js中绘制4个点 // 创建点的几何体 const vertices new Float32Array([0.0, 0.0, 0.0, // 点11.0, 0.0, 0.0, // 点20.0, 1.0, 0.0, // 点30.…

DataWhale AI春训营 问题汇总

1.没用下载训练集导致出错&#xff0c;爆错如下。 这个时候需要去比赛官网下载对应的初赛训练集 unzip -d /mnt/workspace/sais_third_new_energy_baseline/data /mnt/workspace/sais_third_new_energy_baseline/初赛训练集.zip 在命令行执行这个命令解压 2.没定义测试集 te…

CANFD技术在新能源汽车通信网络中的应用与可靠性分析

一、引言 新能源汽车产业正处于快速发展阶段&#xff0c;其电子系统复杂度不断攀升&#xff0c;涵盖众多传感器、控制器与执行器。高效通信网络成为确保新能源汽车安全运行与智能功能实现的核心要素。传统CAN总线因带宽限制&#xff0c;难以满足高级驾驶辅助系统&#xff08;A…

Python字典深度解析:高效键值对数据管理指南

一、字典核心概念解析 1. 字典定义与特征 字典&#xff08;Dictionary&#xff09;是Python中​​基于哈希表实现​​的无序可变容器&#xff0c;通过键值对存储数据&#xff0c;具有以下核心特性&#xff1a; ​​键值对结构​​&#xff1a;{key: value}形式存储数据​​快…

C++中unique_lock和lock_guard区别

目录 1.自动锁定与解锁机制 2.灵活性 3.所有权转移 4.可与条件变量配合使用 5.性能开销 在 C 中&#xff0c;std::unique_lock 和 std::lock_guard 都属于标准库 <mutex> 中的互斥锁管理工具&#xff0c;用于简化互斥锁的使用并确保线程安全。但它们存在一些显著区别…

Nvidia显卡架构演进

1 简介 显示卡&#xff08;英语&#xff1a;Display Card&#xff09;简称显卡&#xff0c;也称图形卡&#xff08;Graphics Card&#xff09;&#xff0c;是个人电脑上以图形处理器&#xff08;GPU&#xff09;为核心的扩展卡&#xff0c;用途是提供中央处理器以外的微处理器帮…

下载electron 22.3.27 源码错误集锦

下载步骤同 electron源码下载及编译_electron源码编译-CSDN博客 问题1 从github 下载 dugite超时&#xff0c;原因没有找到 Validation failed. Expected 8ea2d0d3c9d9e4615069913207371ffe892dc10fb93975972f2f6e668f2e3b3a but got e3b0c44298fc1c149afbf4c8996fb92427ae41e…

洛谷P1120 小木棍

#算法/进阶搜索 思路: 首先,最初始想法,将我们需要枚举的长木棍个数计算出来,在dfs中,我们先判断,此时枚举这根长木棍需要的长度是否为0,如果为0,我们就枚举下一个根木棍,接着再判断,此时仍需要枚举的木棍个数是否为0,如果为0,代表我们这种方案可行,直接打印长木棍长度,接着我们…

Linux教程-常用命令系列二

文章目录 1. 系统管理常用命令1. useradd - 创建用户账户功能基本用法常用选项示例 2. passwd - 管理用户密码功能基本用法常用选项示例 3. kill - 终止进程功能基本用法常用信号示例 4. date - 显示和设置系统时间功能基本用法常用选项时间格式示例 5. bc - 高精度计算器功能基…

18、TimeDiff论文笔记

TimeDiff **1. 背景与动机****2. 扩散模型基础****3. TimeDiff 模型****3.1 前向扩散过程****3.2 后向去噪过程** 4、TimeDiff&#xff08;架构&#xff09;原理训练推理其他关键点解释 DDPM&#xff08;相关数学&#xff09;1、正态分布2、条件概率1. **与多个条件相关**&…

整合SSM——(SpringMVC+Spring+Mybatis)

目录 SSM整合 创建项目 导入依赖 配置文件 SpringConfig MyBatisConfig JdbcConfig ServletConfig SpringMvcConfig 功能模块 测试 业务层接口测试 控制层测试 SSM是Java Web开发中常用的三个主流框架组合的缩写&#xff0c;分别对应Spring、Spring MVC、MyBatis…

P1042【深基8,例1】乒乓球

【题目背景】国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革&#xff0c;以推动乒乓球运动在全球的普及。其中 11 分制改革引起了很大的争议&#xff0c;有一部分球员因为无法适应新规则只能选择退役。华华就是其中一位&#xff0c;他退役之后走上了乒乓球研究工作…

ubuntu24.04上使用qemu和buildroot模拟vexpress-ca9开发板构建嵌入式arm linux环境

1 准备工作 1.1 安装qemu 在ubuntu系统中使用以下命令安装qemu。 sudo apt install qemu-system-arm 安装完毕后&#xff0c;在终端输入: qemu- 后按TAB键&#xff0c;弹出下列命令证明安装成功。 1.2 安装arm交叉编译工具链 sudo apt install gcc-arm-linux-gnueabihf 安装之…

用 R 语言打造交互式叙事地图:讲述黄河源区生态变化的故事

目录 🌟 项目背景:黄河源头的生态变迁 🧰 技术栈介绍 🗺️ 最终效果预览 💻 项目构建步骤 1️⃣ 数据准备 2️⃣ 构建 Leaflet 地图 3️⃣ 使用 scrollama 实现滚动触发事件 4️⃣ 使用 R Markdown / Quarto 打包发布 🎬 效果展示截图 📦 完整代码仓库 …

CTF--秋名山车神

一、原网页&#xff1a; 二、步骤&#xff1a; 1.尝试用计算器计算&#xff1a; 计算器溢出&#xff0c;无法正常计算 2.使用python计算&#xff1a; 得出计算结果为&#xff1a;1864710043732437134701060769 3.多次刷新页面&#xff1a; 发现变量为value&#xff0c;要用pos…

CRC实战宝典:从原理到代码,全面攻克循环冗余校验

CRC实战宝典&#xff1a;从原理到代码&#xff0c;全面攻克循环冗余校验 github开源&#xff1a;CRC软硬件协同测试项目 CRC 简介 CRC&#xff08;循环冗余校验&#xff09;是一种强大的错误检测技术&#xff0c;广泛应用于数字网络和存储系统。它是确保数据完整性的重要方法…

【大模型】DeepSeek + Coze 打造个人专属AI智能体使用详解

目录 一、前言 二、AI智能体介绍 2.1 什么是AI智能体 2.2 AI智能体核心能力 2.3 AI智能应用场景 三、coze 介绍 3.1 coze是什么 3.1.1 平台概述 3.1.2 平台适用人群 3.2 平台核心功能 3.3 coze可以做什么 3.4 为什么选择coze 四、coze 搭建AI智能体操作实践 4.1 搭…