堆的介绍与堆的实现和调整

个人主页:Lei宝啊

愿所有美好如期而遇


目录

​​堆的介绍:

关于堆的实现及相关的其他问题:

堆的初始化:

堆的销毁:

插入建堆:

堆向上调整:

交换两个节点的值:

堆向下调整:

删除根节点:

求堆顶数据:

打印堆的每一个节点的值:

堆排序:

堆的节点数量:

判断堆是否为空:

创建一个多数据文件:

TopK问题(综合):

向上/向下调整建堆哪个时间复杂度更优秀?


​​堆的介绍:

首先,堆是不完全二叉树。

不完全二叉树:除了最后一层外,其他层每一层都是满的,最后一层节点从左到右排。

再者,堆分为大堆和小堆

大堆:父母节点的值大于等于孩子节点

小堆:父母节点的值小于等于孩子节点

关于堆的实现及相关的其他问题:

我们在主函数中将定义一个Heap hp;

typedef int Heaptype;
typedef struct Heap
{Heaptype* data;int size;int capacity;
}Heap;//堆的初始化
void HeapInit(Heap* php);
//堆的销毁
void HeapDestroy(Heap* php);
//插入建堆
void HeapPush(Heap* php, Heaptype num);
//堆向上调整
void Ajustup(Heaptype* a, int child);
//交换两个节点的值
void Swap(Heaptype* p1, Heaptype* p2);
//堆向下调整
void AjustDown(Heaptype* a, int n, int parent);
//删除根节点
void HeapPop(Heap* php);
//求得堆顶数据
Heaptype HeapTop(Heap* php);
//打印堆的每一个节点的值
void HeapPrint(Heaptype* arr, int size);
//堆排序
void HeapSort(Heaptype* arr, int size);
//堆的节点数量
void HeapSize(Heap* php);
//判读堆是否为空
void HeapEmpty(Heap* php);
//创建一个多数据文件
void CreateNDate();
//TopK问题
void PrintTopK(int k);

堆的初始化:

void HeapInit(Heap* php)
{assert(php);php->data = NULL;php->size = 0;php->capacity = 0;
}

堆的销毁:

void HeapDestroy(Heap* php)
{assert(php);free(php->data);php->data = NULL;php->size = 0;php->capacity = 0;
}

插入建堆:

void HeapPush(Heap* php, Heaptype num)
{assert(php);if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;Heaptype* temp = (Heaptype*)realloc(php->data, sizeof(Heaptype) * newcapacity);if (temp == NULL){perror("realloc fail");printf("\n%s", __LINE__);}php->data = temp;php->capacity = newcapacity;}php->data[php->size++] = num;//插入后当即向上调整,以保证还是个堆Ajustup(php->data, php->size - 1);
}

堆向上调整:

//堆向上调整,调整一轮,建堆就循环插入去建
void Ajustup(Heaptype* a, int child)
{int parent = (child - 1) / 2;//当child == 0 的时候,parent也为0while (child > 0){if (a[child] < a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}

交换两个节点的值:


void Swap(Heaptype* p1, Heaptype* p2)
{Heaptype temp = *p1;*p1 = *p2;*p2 = temp;}

堆向下调整:

//堆向下调整
void AjustDown(Heaptype* a, int n, int parent)
{//从叶子节点开始int child = parent * 2 + 1;while (child < n){//找出最小孩子if (child + 1 < n && a[child] > a[child + 1]){child++;}else{if (a[parent] > a[child]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}	else{break;}}}}

删除根节点:

void HeapPop(Heap* php)
{assert(php);assert(php->size > 0);Swap(&php->data[0], &php->data[php->size - 1]);AjustDown(php->data, php->size - 1, 0);php->size--;
}

求堆顶数据:

Heaptype HeapTop(Heap* php)
{assert(php);return php->data[0];
}

打印堆的每一个节点的值:

void HeapPrint(Heaptype* arr, int size)
{assert(arr);for (int i = 0; i < size; i++){printf("%d ", arr[i]);}
}

堆排序:

void HeapSort(Heaptype* arr, int size)
{assert(arr);//向上调整建堆(小堆)/*int num = size;for (int i = 0; i < num; i++){Ajustup(arr, i);}*///向下调整建堆int last = (size - 1 - 1) / 2;for (int i = last; i >= 0; i--){AjustDown(arr, size, i);}//排序int end = size - 1;while (end > 0){Swap(&arr[0], &arr[end]);AjustDown(arr, end, 0);end--;}
}

堆的节点数量:

void HeapSize(Heap* php)
{assert(php);return php->size;
}

判断堆是否为空:

void HeapEmpty(Heap* php)
{assert(php);return php->size == 0;
}

创建一个多数据文件:

void CreateNDate()
{int n = 10000;srand((unsigned int)time(NULL));const char* file = "heap.txt";FILE* pf = fopen(file, "w");{if (pf == NULL){perror("fopen fail");return;}}for (int i = 0; i < n; i++){int num = rand() % 1000000;fprintf(pf, "%d\n", num);}fclose(pf);}

TopK问题(综合):

void PrintTopK(int k)
{Heaptype* arr = (Heaptype*)malloc(sizeof(Heaptype) * k);	if (arr == NULL){perror("malloc fail");return;}FILE* pf = fopen("heap.txt", "r");if (pf == NULL){perror("fopen fail");return;}for (int i = 0; i < k; i++){fscanf(pf, "%d", &arr[i]);}//调整为小堆int n = (k - 1 - 1) / 2;for (int i = n; i >= 0; i--){AjustDown(arr, k, i);}//由于我们建1的是大小为k的堆,堆顶的数值最小,当新的数据大于堆//顶时,进堆,而堆顶的数据被替换,之后堆向下调整int a = 0;while (fscanf(pf, "%d", &a) != EOF){if (a > arr[0]){arr[0] = a;AjustDown(arr, k, 0);}}//此时堆里的数据是最大的k个数	for (int i = 0; i < k; i++){printf("%d ", arr[i]);}fclose(pf);free(arr);
}

向上/向下调整建堆哪个时间复杂度更优秀?

答案是堆向下调整,时间复杂度为O(N),堆向上调整时间复杂度为O(N*logN)。


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

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

相关文章

SpringCache -- Redis --- 配置与缓存使用--配置过期时间

写在前面&#xff1a; 学redis&#xff0c;还是得搭配SpringCache来玩一玩。 前置内容 win安装redis基础 springboot使用redis 文章目录 导入依赖配置cache 使用CacheableCachePutCacheEvict 配置过期时间依据cacheName设置在注解上截取过期时间 导入依赖 <!--redis依赖…

邓俊辉《数据结构》→ “2.6.5 二分查找(版本A)”之“成功查找长度”递推式推导

【问题描述】 邓俊辉的《数据结构&#xff08;C语言版&#xff09;&#xff08;第3版&#xff09;》&#xff08;ISBN&#xff1a;9787302330646&#xff09;中&#xff0c;开始于第48页的“2.6.5 二分查找&#xff08;版本A&#xff09;”内容在第50页详述了“成功查找长度”的…

uniapp 点击事件-防重复点击

uniapp 点击事件-防重复点击 1、common文件并创建anti-shake.js文件 // 防止处理多次点击 function noMoreClicks(methods, info) {// methods是需要点击后需要执行的函数&#xff0c; info是点击需要传的参数let that this;if (that.noClick) {// 第一次点击that.noClick f…

vue循环滚动字幕

在Vue.js中创建一个循环滚动字幕的效果通常需要使用一些CSS和JavaScript来实现。以下是一个简单的示例&#xff0c;展示如何使用Vue.js创建一个循环滚动字幕的效果&#xff1a; 首先&#xff0c;在HTML中创建一个Vue实例&#xff0c;并添加一个包含滚动字幕的容器元素&#xff…

vue消息订阅与发布

1.知识点 是一种组件间通信的方式&#xff0c;适用于任意组件间通信 2.使用步骤 “消息订阅与发布”可依赖的第三方很多&#xff0c;这里使用pubsub-js库 1.安装pubsub&#xff1a;npm i pubsub-js 2.引入&#xff1a;import pubsub from pubsub-js 3.接收数据&#xff1a;A组件…

【数据结构】排序合集(万字详解)

文章目录 前言插入排序希尔排序选择排序堆排序快速排序hoare原生版本挖坑法前后指针法三数取中优化随机数取key优化三路划分版非递归 归并排序递归非递归调整边界单次归并单次拷贝 总结 前言 排序&#xff0c;以字面意思来说就是通过特定的算法将一组或多组无序或者接近有序的…

02Redis的命令行客户端和桌面客户端的下载和安装

Redis桌面客户端 安装完成Redis服务,我们就可以在Redis的客户端操作Redis的数据库实现数据的CRUD了,客户端分为三类命令行客户端, 图形化桌面客户端,编程客户端 命令行客户端 Redis安装完成后就自带了命令行客户端: redis-cli [options] [commonds] -h选项&#xff1a;指定…

矢量图形编辑软件illustrator 2023 mac软件特点

illustrator 2023 mac是一款矢量图形编辑软件&#xff0c;用于创建和编辑排版、图标、标志、插图和其他类型的矢量图形。 illustrator mac软件特点 矢量图形&#xff1a;illustrator创建的图形是矢量图形&#xff0c;可以无限放大而不失真&#xff0c;这与像素图形编辑软件&am…

计算机网络 实验二 交换机的基本配置

实验二 交换机的基本配置 实验目的 • 掌握交换机的配置方式及切换命令&#xff1b; • 掌握交换机端口的基本配置&#xff1b; • 掌握交换机mac地址的查看与管理方法。 实验设备 以太网交换机一台服务器一台PC机五台配置电缆、网线若干 网络拓扑及IP地址分配 给计算…

题目 1065: 二级C语言-最小绝对值

输入格式 十个数 输出格式 交换后的十个数 样例输入 10 2 30 40 50 60 70 80 90 100 样例输出 10 100 30 40 50 60 70 80 90 2 我对这题用了两个数组&#xff0c;一个存储原来的值&#xff0c;一个是镜像的绝对值。 找最小的数和序号就在镜像里&#xff0c;遍历寻找就行 #i…

Docker部署ActiveMQ消息中间件

1、准备工作 docker pull webcenter/activemq:5.14.3 Pwd"/data/software/activemq" mkdir ${Pwd}/data -p2、运行容器 docker run -d --name activemq \-p 61616:61616 \-p 8161:8161 \-v ${Pwd}/data:/opt/activemq/data \-v /etc/localtime:/etc/localtime \--r…

服务器补丁管理软件

随着漏洞的不断上升&#xff0c;服务器修补是增强企业网络安全的典型特征。作为业务关键型机器&#xff0c;计划服务器维护的停机时间无疑是一件麻烦事。但是&#xff0c;借助高效的服务器补丁管理软件&#xff08;如 Patch Manager Plus&#xff09;&#xff0c;管理员可以利用…

UE5读取json文件

一、下载插件 在工程中启用 二、定义读取外部json文件的函数&#xff0c;参考我之前的文章 ue5读取外部文件_艺菲的博客-CSDN博客 三、读取文件并解析为json对象 这里Load Text就是自己定义的函数&#xff0c;ResourceBundle为一个字符串常量&#xff0c;通常是读取的文件夹…

UML活动图

在UML中&#xff0c;活动图本质上就是流程图&#xff0c;它描述系统的活动、判定点和分支等&#xff0c;因此它对开发人员来说是一种重要工具。 活动图 活动是某件事情正在进行的状态&#xff0c;既可以是现实生活中正在进行的某一项工作&#xff0c;也可以是软件系统中某个类…

[Linux] 1.Linux的简介

Linux是一套免费使用和自由传播的类Unix操作系统&#xff0c;是一个多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和64位硬件。 Linux发行版&#xff1a;基于Linux内核定制不同风格的Linux ubuntu:嵌入式开发 …

题目 1069: 二级C语言-寻找矩阵最值

输入一个正整数n (1≤ n ≤6),再输入一个n 行n列的矩阵&#xff0c;找出该矩阵中绝对值最大的元素以及它的行下标和列下标。 输入格式 n nxn &#xff08;矩阵的数据&#xff09; 输出格式 数 行 列 样例输入 2 1 2 3 4样例输出 4 2 2 二维矩阵的创建cpp代码实现&a…

Linux实验一

#include <stdio.h> #include <stdlib.h> int main() { printf("hello ,\n"); printf("world\n"); // 使用 exit(0) 结束进程 exit(0); } #include <stdio.h> #include <unistd.h> int main() { printf("hello ,\n")…

Ubuntu上通过源码方式安装Redis

上一篇文章Ubuntu上安装、使用Redis的详细教程已经介绍了再Ubuntu操作系统上安装Redis的详细过程&#xff0c;但是因为安装的Redis只有最主要的配置文件和redis-server&#xff0c;为了更深入地学习Redis和进行更复杂的操作&#xff0c;需要安装一个完整的Redis服务。 这篇文章…

day-53 代码随想录算法训练营(19)动态规划 part 14

1143.最长公共子序列&#xff08;坐牢&#xff09; class Solution { public:int longestCommonSubsequence(string text1, string text2) {int ntext1.size(),mtext2.size();vector<vector<int>>dp(n1,vector<int>(m1,0));for(int i1;i<n;i){for(int j1…

SEO方案尝试--Nuxtjs项目基础配置

Nuxtjs 最新版 Nuxt3 项目配置 安装nuxtjs 最新版 Nuxt3 参考官网安装安装插件安装ElementPlus页面怎么跳转&#xff0c;路由怎么实现404页面该怎么配置配置 网页的title 安装nuxtjs 最新版 Nuxt3 参考官网安装 安装插件 安装ElementPlus 安装 Element Plus 和图标库 # 首先&…