堆(数据结构)

堆的概念及结构

  如果有一个关键码的集合K = { , , ,…, },把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足: <= 且 <=  ( >= 且 >= ) i = 0,1,2…,则称为小堆(或大堆)。

    将根节点最大的堆叫做最大堆或大根堆

   节点最小的堆叫做最小堆或小根堆

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

1.下列关键字序列为堆的是:()
A 100,60,70,50,32,65
B 60,70,65,50,32,100
C 65,100,70,32,50,60
D 70,65,100,32,50,60
E 32,50,100,70,65,60
F 50,100,70,65,60,32
2.已知小根堆为8,15,10,21,34,16,12,删除关键字 8 之后需重建堆,在此过程中,关键字之间的比较次数是()。
A 1
B 2
C 3
D 4
3.一组记录排序码为(5 11 7 2 3 17),则利用堆排序方法建立的初始堆为
A(11 5 7 2 3 17)
B(11 5 7 2 17 3)
C(17 11 7 2 3 5)
D(17 11 7 5 3 2)
E(17 7 11 3 5 2)
F(17 7 11 3 2 5)
4.最小堆[0,3,2,5,7,4,6,8],在删除堆顶元素0之后,其结果是()
A[3,2,5,7,4,6,8]
B[2,3,5,7,4,6,8]
C[2,3,4,5,7,8,6]
D[2,3,4,5,6,7,8]

选择题答案:

1.A
2.C
3.C
4.C

堆的实现

1 堆向下调整算法

  现在我们给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根节点开始的向下调整算法可以把它调整成一个小堆。向下调整算法有一个前提:左右子树必须是一个堆,才能调整。

int array[] = {27,15,19,18,28,34,65,49,25,37};

堆的创建

  下面我们给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但是还不是一个堆,现在我们通过算法,把它构建成一个堆。根节点左右子树不是堆,我们怎么调整呢?

在此我们有两种建堆方法:
  1. 利用向上调整的方法,从第2 个节点开始一直调整到最后,就可以调整成堆。

  2. 利用向下调整的方法,我们从倒数的第一个非叶子节点的子树开始调整,一直调整到根节点的树,就可以调整成堆。

但是第一种建堆的时间复杂度为 O(N*logN),第二种建堆的时间复杂度为O(N)

所以我们在此用第二种方法

堆的插入

  先插入一个10到数组的尾上,再进行向上调整算法,直到满足堆。

堆的删除

  删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法

堆的代码实现

Heap.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
#include<string.h>


typedef int HeapDataType;
typedef struct Heap
{
	HeapDataType* a;
	int size;
	int capacity;
}Heap;


void HeapInit(Heap* ph);

void HeapInitArray(HeapDataType* a, Heap* ph,int n);
void HeapDestroy(Heap* ph);
void HeapPush(Heap* ph, HeapDataType x);
void HeapPop(Heap* ph);
HeapDataType HeapTop(Heap* ph);
void AdjustUp(HeapDataType* a, int child);
void AdjustDown(HeapDataType* pa, int n, int parent);
bool HeapEmpty(Heap* ph);

Heap.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"



void HeapInit(Heap* ph)
{
	assert(ph);
	ph->a = NULL;
	ph->size = 0;
	ph->capacity = 0;
}
void HeapDestroy(Heap* ph)
{
	assert(ph);
	ph->size = 0;
	ph->capacity = 0;
	free(ph->a);
	ph->a = NULL;
}

//利用其它数组数据,建造一个堆存储数据
void HeapInitArray(Heap* ph,HeapDataType* a, int n)
{
	assert(ph);
	HeapDataType* tmp = (HeapDataType*)malloc(sizeof(HeapDataType) * n);
	if (tmp == NULL)
	{
		perror("malloc fail!");
		exit(-1);
	}
	ph->a = tmp;
	ph->size = ph->capacity = n;
	memcpy(ph->a , a , n*sizeof(HeapDataType));

	//向上调整建堆,时间复杂度O(N*logN)
	//for (int i = 1; i < ph->size; i++)
	//{
	//	AdjustUp(ph->a,i);
	//}

	//向下调整建堆,从第一个不为叶子的节点,时间复杂度O(N)
	for(int i = (ph->size - 1 - 1)/2; i >= 0; i--)
	{
		AdjustDown(ph->a,n,i);
	}
}

void Swap(HeapDataType*p1, HeapDataType*p2)
{
	HeapDataType tmp=*p1;
	*p1 = *p2;
	*p2 = tmp;
}

void AdjustDown(HeapDataType* a,int n , int parent)
{
	int child = parent*2 + 1;
	while (child < n)
	{
		if (child + 1<n && a[child + 1] < a[child])
		{
			child++;
		}

		if (a[parent] > a[child])
		{
			Swap(&a[parent],&a[child]);
			parent = child;
			child = parent * 2 +1;
		}
		else
		{
			break;
		}
	}
}
//建造小堆
void AdjustUp(HeapDataType* a, int child)
{
	int parent = (child - 1) / 2;
	//while(parent>=0)
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}
void HeapPush(Heap* ph, HeapDataType x)
{
	assert(ph);
	if (ph->size == ph->capacity)
	{
		int newcapacity = ph->capacity == 0 ? 4 : ph->capacity * 2;
		HeapDataType* tmp=(HeapDataType*)realloc(ph->a,newcapacity*sizeof(HeapDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(-1);
		}
		ph->a = tmp;
		ph->capacity = newcapacity;
	}
	ph->size++;
	ph->a[ph->size - 1] = x;
	AdjustUp(ph->a, ph->size - 1);
}
void HeapPop(Heap* ph)
{
	assert(ph);
	//必须有数据
	assert(ph->size);
	Swap(&ph->a[0], &ph->a[ph->size - 1]);
	ph->size--;
	AdjustDown(ph->a,ph->size,0);

}
HeapDataType HeapTop(Heap* ph)
{
	assert(ph);
	return ph->a[0];
}
bool HeapEmpty(Heap* ph)
{
	assert(ph);
	return ph->size == 0;
}

Test.c

#include"Heap.h"
int main()
{
	//Heap heap1;
	//HeapInit(&heap1);
	//HeapPush(&heap1,1);
	//HeapPush(&heap1,54);
	//HeapPush(&heap1,48);
	//HeapPush(&heap1,48);
	//HeapPush(&heap1,15);
	//HeapPush(&heap1,35);
	//int a []={21,54,87,64,87,15};

	//Heap heap2;
	//HeapInit(&heap2);
	//for (int i = 0; i < (sizeof(a)/sizeof(int)); i++)
	//{
	//	HeapPush(&heap2, a[i]);
	//}
	//while (!HeapEmpty(&heap2))
	//{
	//	printf("%d\n", HeapTop(&heap2));
	//	HeapPop(&heap2);
	//}


	//int a[] = { 21,54,87,64,87,15 };
	//Heap heap2;
	//HeapInitArray(&heap2 ,a,sizeof(a)/sizeof(HeapDataType));//建立了小堆
	//HeapDestroy(&heap2);

	return 0;
}

这个博客如果对你有帮助,给博主一个免费的点赞就是最大的帮助

欢迎各位点赞,收藏和关注哦

如果有疑问或有不同见解,欢迎在评论区留言哦

后续我会一直分享双一流211西北大学软件(C,数据结构,C++,Linux,MySQL)的学习干货以及重要代码的分享

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

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

相关文章

Python爬虫案例-爬取主题图片(可以选择自己喜欢的主题)

2024年了&#xff0c;你需要网络资源不能还自己再慢慢找吧&#xff1f; 跟着博主一块学习如何利用爬虫获取资源&#xff0c;从茫茫大海中寻找那个她到再妹子群中找妹子&#xff0c;闭着眼睛都可以找到合适的那种。文章有完整示例代码&#xff0c;拿过来就可以用&#xff0c;欢迎…

【C语言】数据在内存中的存储(包含大小端字节序问题)~

一、前言 我们在刚开始学习C语言的时候&#xff0c;就接触到了很多数据的不同类型。我们也知道&#xff0c;数据是存储在一块内存空间的&#xff0c;且我们只知道数据的类型决定着&#xff0c;该数据在内存中所占内存空间的大小&#xff0c;且超过一个字节的数据在内存中存储的…

【项目实践Day06】异步请求与同步请求+Ajax+微信小程序上实现发送异步请求

什么是同步和异步 同步 在主线程上排队执行的任务&#xff0c;只有前一个任务执行完毕&#xff0c;才能继续执行下一个任务。也就是一旦调用开始&#xff0c;就必须等待其返回结果&#xff0c;程序的执行顺序和任务排列顺序一致。客户端必须等待服务器端的响应。在等待的期间客…

Android源码阅读 SharedPreferences - 1

目录 前言 正文 SharedPreferences.java PreferenceManager.java ContextImpl.java 前言 由于笔者目前水平限制&#xff0c;表达能力有限&#xff0c;尽请见谅。 SharedPreferences提供了一种轻量级的数据存储方式&#xff0c;允许保存和获取简单的键值对。它适用于保存少…

转座子插入序列分析1-GENE-IS分析管道

如果你使用 GENE-IS: Saira Afzal et al。 &#xff0c;2016请引用这篇研究文章。GENE-IS: time-efficient and accurate analysis of viral integration events in large-scale gene therapy data. Molecular Therapy - Nucleic Acids 2016, vol. 6:133-139. DOI:https://doi.…

做好外贸网站SEO优化,拓展海外市场

随着全球贸易的发展和互联网的普及&#xff0c;越来越多的外贸企业将目光投向了网络&#xff0c;希望通过建立网站来拓展海外市场。然而&#xff0c;在竞争激烈的外贸市场中&#xff0c;要让自己的网站脱颖而出&#xff0c;吸引更多的目标客户&#xff0c;就需要进行有效的SEO优…

StarRocks 记录

《实时数仓StarRocks集群部署》

提升Spring Boot应用性能的秘密武器:揭秘@Async注解的实用技巧

引言 在日常业务开发中&#xff0c;异步编程已成为应对并发挑战和提升应用程序性能的关键策略。传统的同步编程方式&#xff0c;由于会阻碍主线程执行后续任务直至程序代码执行结束&#xff0c;不可避免地降低了程序整体效率与响应速度。因此&#xff0c;为克服这一瓶颈&#…

win11环境安装VmwareLinux

VMware 安装Vmware 操作系统&#xff1a; win11 VM版本&#xff1a; 重启系统 输入许可证秘钥 安装centos finalshell连接linux服务 配置虚拟机运行状态 查询linux服务器的ip地址 下载finalshell 访问FinalShell官网 (hostbuf.com)

Spring6入门到高级-动力节点老杜

文章目录 OCP开闭原则依赖倒置原则控制反转依赖注入DISet方法注入构造注入 Sping特点代理模式代理模式中的角色动态代理JDK动态代理newProxyInstance() 的三个参数 JDK实现代理的步骤第一步&#xff1a;创建目标对象第二步&#xff1a;创建代理对象第三步&#xff1a;调用代理对…

C语言学习--八种排序算法

目录 排序的概念 1.直接插入排序 基本思想 代码实现 算法分析 2.希尔排序 基本思想 代码实现 算法分析 3.冒泡排序 基本思想 代码实现 算法分析 4.快速排序 基本思想 代码实现 算法分析 5.简单选择排序 基本思想 代码实现 算法分析 6.堆排序 基本思想 代…

合合信息扫描全能王亮相静安区3·15活动,AI扫描带来绿色消费新体验

保护消费者的合法权益&#xff0c;是全社会的共同责任。为优化消费环境、促进品质消费高地建设&#xff0c;打造安全优质和谐的消费环境&#xff0c;上海静安区消保委于3月15日举办静安区2024年“315”国际消费者权益日活动。 “激发消费活力&#xff0c;绿色低碳同行”是本次3…

Vue+SpringBoot打造民宿预定管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用例设计2.2 功能设计2.2.1 租客角色2.2.2 房主角色2.2.3 系统管理员角色 三、系统展示四、核心代码4.1 查询民宿4.2 新增民宿4.3 新增民宿评价4.4 查询留言4.5 新增民宿订单 五、免责说明 一、摘要 1.1 项目介绍 基于…

傻傻分不清目标检测、语义分割和实例分割,看这篇就够了

⭐️ 导言 随着深度学习技术的飞速发展&#xff0c;计算机视觉领域取得了巨大的进步。目标检测、语义分割和实例分割是计算机视觉中的重要任务&#xff0c;它们在图像理解和视频分析等方面发挥着关键作用。本文将深入探讨这三个任务的概念、原理、常用算法以及在实际应用中的案…

(css)vue 自定义背景 can‘t resolve

(css)vue 自定义背景 can’t resolve 旧写法&#xff1a; background-image: url(/assets/images/step-bg.jpg);background-size: 100% 100%; 新写法&#xff1a; background-image: url(~/assets/images/step-bg.jpg);background-size: 100% 100%; 解决参考&#xff1a;https…

shopee无货源出单了怎么发货?shopee怎么做无货源?

在Shopee的电商大舞台上&#xff0c;“无货源出单”就像是一场神奇的魔术表演。你的店铺是舞台&#xff0c;买家的订单是观众的掌声&#xff0c;而你&#xff0c;就是那位神秘的魔术师。订单来了&#xff0c;你却没有货&#xff1f;这可不是什么障碍&#xff0c;因为你有着更为…

算法详解——选择排序和冒泡排序

一、选择排序 选择排序算法的执行过程是这样的&#xff1a;首先&#xff0c;算法遍历整个列表以确定最小的元素&#xff0c;接着&#xff0c;这个最小的元素被置换到列表的开头&#xff0c;确保它被放置在其应有的有序位置上。接下来&#xff0c;从列表的第二个元素开始&#x…

[MySQL]数据库基础

文章目录 1.连接服务器2.理解mysql3.初见数据库4.主流数据库5.服务器&#xff0c;数据库&#xff0c;表关系6.数据逻辑存储7.MySQL架构8.SQL分类9.存储引擎 1.连接服务器 mysql -h 127.0.0.1 -P 3306 -u root -p -h&#xff1a;指明登录部署mysql服务的主机。没有写 -h 127.0.…

【链表】Leetcode 21. 合并两个有序链表【简单】

合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] 解题思路 1、比较两个链表的头结点&#xff0c;选择其…

jumpserver管理集群

git地址&#xff1a;https://github.com/jumpserver/jumpserver.git 1、下载 jumpserver 需要docker来拉取镜像&#xff0c;没有的话会自动下载docker curl -sSL https://resource.fit2cloud.com/jumpserver/jumpserver/releases/latest/download/quick_start.sh | bash 拉取的…