数据结构:顺序二叉树(堆)

news2024/9/20 2:06:38

目录

前言

一、堆的实现

 1.1 头文件

1.2 堆的初始化及销毁

1.3  堆的插入

1.4 堆的删除

1.5 取堆顶数据和判空


前言

     前面我们讲了二叉树有顺序结构和链式结构,今天就来讲一下顺序结构

    普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结 构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统 虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

一、堆的实现

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

 1.1 头文件

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}Heap;

//堆的初始化
void HeapInit(Heap*hp);
// 堆的销毁
void HeapDestory(Heap* hp);
// 堆的插入
void HeapPush(Heap* hp, HPDataType x);
// 堆的删除
void HeapPop(Heap* hp);
// 取堆顶的数据
HPDataType HeapTop(Heap* hp);
// 堆的判空
bool HeapEmpty(Heap* hp);

    写入我们需要用到的头文件以及堆的基础结构还有用到的堆的功能函数名。

1.2 堆的初始化及销毁

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

    这个没什么还说的,就是把数据都置空了。

1.3  堆的插入

void HeapPush(Heap* hp, HPDataType x)
{
	assert(hp);
	if (hp->size == hp->capacity)
	{
		int newcapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;
		HPDataType* tem = (HPDataType*)realloc(hp->a, sizeof(HPDataType) * newcapacity);
		hp->capacity = newcapacity;
		hp->a = tem;
	}
	hp->a[hp->size] = x;
	hp->size++;
	adjustup(hp->a, hp->size-1);
}

这里我们会用到向上调整算法 

void swap(HPDataType* a, HPDataType* b)
{
	HPDataType tem = *a;
	*a = *b;
	*b = tem;
}
void adjustup(HPDataType* a, HPDataType child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[parent] > a[child])
		{
			swap(&a[parent], &a[child]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

     插入数据后要保持父节点比子节点小的性质,要把数据一步步向上调整。

1.4 堆的删除

void HeapPop(Heap* hp)
{
	assert(hp);
	swap(&hp->a[0], &hp->a[hp->size - 1]);
	hp->size--;
	adjustdown(hp->a, hp->size,0);
}

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

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

这里给个例子:

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

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

1.5 取堆顶数据和判空

HPDataType HeapTop(Heap* hp)
{
	return hp->a[0];
}

    因为是基于数组写的,所以取堆顶就很简单了。

bool HeapEmpty(Heap* hp)
{
	return hp->size == 0;
}

    如果数据位空了,那么堆就是空的。

二、完整源码

dui.h

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}Heap;


void HeapInit(Heap*hp);

void HeapDestory(Heap* hp);

void HeapPush(Heap* hp, HPDataType x);

void HeapPop(Heap* hp);

HPDataType HeapTop(Heap* hp);

int HeapSize(Heap* hp);

bool HeapEmpty(Heap* hp);

 dui.c

#include"dui.h"
void HeapInit(Heap* hp)
{
	assert(hp);
	hp->a = NULL;
	hp->size = hp->capacity = 0;
}
void HeapDestory(Heap* hp)
{
	assert(hp);
	free(hp->a);
	hp->a = NULL;
	hp->size = hp->capacity = 0;
}
void swap(HPDataType* a, HPDataType* b)
{
	HPDataType tem = *a;
	*a = *b;
	*b = tem;
}
void adjustup(HPDataType* a, HPDataType child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[parent] > a[child])
		{
			swap(&a[parent], &a[child]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}
void HeapPush(Heap* hp, HPDataType x)
{
	assert(hp);
	if (hp->size == hp->capacity)
	{
		int newcapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;
		HPDataType* tem = (HPDataType*)realloc(hp->a, sizeof(HPDataType) * newcapacity);
		hp->capacity = newcapacity;
		hp->a = tem;
	}
	hp->a[hp->size] = x;
	hp->size++;
	adjustup(hp->a, hp->size-1);
}
void adjustdown(HPDataType* a, HPDataType n,HPDataType parent)
{
	HPDataType child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child + 1] < a[child])
		{
			child++;
		}
		if (a[child] < a[parent])
		{
			swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
void HeapPop(Heap* hp)
{
	assert(hp);
	swap(&hp->a[0], &hp->a[hp->size - 1]);
	hp->size--;
	adjustdown(hp->a, hp->size,0);
}
HPDataType HeapTop(Heap* hp)
{
	return hp->a[0];
}
int HeapSize(Heap* hp)
{
	return hp->size;
}
bool HeapEmpty(Heap* hp)
{
	return hp->size == 0;
}

   

    还是要自己动手写一边才能有印象,写完每个功能点最好一个一个的去测试,这样就不会那么麻烦,更容易知道错哪了,全部写写完再测试,没错误还好说,有错的话,找起来会很痛苦的。


     本篇内容就到这里了,希望对各位有帮助,如果有错误欢迎指出。

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

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

相关文章

HTTP请求的流转路径,从Tomcat到SpringMVC

本文主要讲一下&#xff0c;一个HTTP请求在后端服务的流转路径&#xff0c;Tomcat等一众servlet容器如何定义了Web应用的基础样貌&#xff0c;后来的MVC框架又是如何弱化了servlet的存在&#xff0c;改为自己实现请求派发的。 前些日子我写了十几篇文章来介绍Tomcat的架构&…

AI在医学领域:联邦学习 (FL) 在肿瘤学的应用综述

关键词&#xff1a;联邦学习 (Federated Learning, FL)、机器学习 (Machine Learning, ML)、肿瘤学 (Oncology)、数据隐私 (Data Privacy)、精准医疗 (Precision Medicine)、多模态 (Multi-modal) 肿瘤学正在经历快速的变革&#xff0c;这得益于机器学习&#xff08;ML&#xf…

tinymce字体为48px后再设置numlist数字列表导致前面的序号字体不对--【已解决】

问题描述&#xff1a; tinymce选择完大号字体&#xff0c;如48px&#xff0c;再选择数字列表&#xff0c;会导致数字列表的序号字体不对。 解决&#xff1a; 演示效果

【C语言篇】C语言常考及易错题整理DAY3

文章目录 选择题整形提升与算术转换左移右移操作符操作符优先级与结合性后置指针变量基本知识 编程题最大连续1的个数完全数计算单词倒排面试题.珠玑妙算两数之和 选择题 整形提升与算术转换 声明以下变量&#xff0c;则表达式: ch/i (f*d – i) 的结果类型为&#xff08; &…

Fal.ai Flux 1-Pro/Viva.ai/哩布哩布AI:AI绘图部分免费工具+原图提示词Prompt

目录 #1 找软件 #2 懂提示词 #3 更难的一步&#xff0c;会英文 我个人认为&#xff0c;想要玩文生图&#xff0c;你要会3个步骤&#xff1a; #1 找软件 主流文生图软件&#xff1a;Midjourney、Stable Diffusion、Dall-E 3 巧了&#xff0c;我用的都是小众、免费的画笔工…

Linux 错误码

目录 一、概述二、含义三、错误处理函数1、IS_ERR2、strerr、perror 一、概述 在 Linux 系统中&#xff0c;错误码是用来表示操作系统运行过程中发生的错误的数字代码。错误码通常由负数表示&#xff0c;0 表示成功&#xff0c;正数表示警告或其他非致命错误。 为了开发者更好…

查询大数据信用需要收费吗?哪个平台好一点?

随着大数据技术被运用到金融行业&#xff0c;不少申贷人都开始了解自己的大数据信用&#xff0c;在查询大数据信用的时候&#xff0c;查询大数据信用需要钱吗?哪个平台好一点?等问题是很多人都比较关心的问题&#xff0c;下面本文就详细为大家详解一下&#xff0c;希望对你了…

基于python的百度迁徙迁入、迁出数据分析(九)

副标题&#xff1a;从百度迁徙数据看——人口虹吸效应 人口虹吸效应&#xff1a;人口虹吸效应是指大城市或中心城市因其经济、文化、教育、医疗等资源的优势&#xff0c;吸引周边地区的人口、资本和其他资源向其集中的一种现象。这种效应在城市化进程中尤其明显&#xff0c;通…

公司起诉员工泄密难吗?如何搜寻有力的证据?专业审计软件助力,追责之路其实不难!

在企业管理中&#xff0c;员工泄密是一个严重的问题&#xff0c;不仅可能损害企业的商业利益&#xff0c;还可能对企业的声誉造成不可挽回的影响。然而&#xff0c;公司起诉员工泄密并非易事&#xff0c;需要满足严格的法律条件和程序&#xff0c;并面临证据收集与举证、法律程…

10款好用的文件加密软件排行榜,2024企业常用的文件加密软件

在数据安全日益受到重视的今天&#xff0c;文件加密软件已成为保护企业敏感信息的重要工具。以下是2024年企业常用的10款好用的文件加密软件排行榜&#xff0c;帮助你选择适合的工具来保护你的文件和数据。 1. 安秉加密软件 安秉加密软件提供用户友好的界面和强大的加密功能。…

使用 nginx 搭建代理服务器(正向代理 https 网站)指南

简介 正向代理 简介 在企业开发环境中&#xff0c;局域网内的设备通常需要通过正向代理服务器访问互联网。正向代理服务器充当中介&#xff0c;帮助客户端请求外部资源并返回结果。局域网内也就是俗称的内网&#xff0c;局域网外的互联网就是外网&#xff0c;在一些特殊场景内…

unity 画线写字

效果 1.界面设置 2.涉及两个脚本UIDraw.cs和UIDrawLine.cs UIDraw.cs using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI;public class UIDraw : MonoBehaviour, IPointerEnterHandler, IPointerEx…

【大数据】什么是数据架构?

目录 一、什么是数据架构&#xff1f; 二、数据架构的发展历程 1. 早期阶段&#xff08;1960年代-1970年代&#xff09; 2. 关系数据库的兴起&#xff08;1970年代-1980年代&#xff09; 3. 数据仓库和数据挖掘&#xff08;1980年代-1990年代&#xff09; 4. 大数据和NoSQL&…

计算机基础|数据溢出

一、概念 在类似C这样的非高级语言存在数值溢出问题&#xff0c;简单概括&#xff1a;高位数据丢失被低位数据占据位置。 二、举例 2.1 以C语言 for循环为例 /*int8_t value range from -128 to 127*/int8_t input;for (input 124; input < 130; input) {printf("%…

《Unity3D网络游戏实战》深入了解TCP

从TCP到铜线 应用层 应用层功能是应用程序&#xff08;游戏程序&#xff09;提供的功能。在给客户端发送“hello”的例子中&#xff0c;程序把“hello”转化成二进制流传递给传输层&#xff08;传送给send方&#xff09;​。操作系统会对二进制数据做一系列加工&#xff0c;使…

嵌入式八股文-网络编程、多线程和进程

网络编程 1. TCP头部结构 TCP固定头部结构 每个TCP报文段都包含着此报文段的TCP头部信息,用于指定源端端口、目的端端口以及管理TCP连接等。完整的TCP头部结构可分为固定头部结构和头部选项两个部分。 32位端口号:包括了16位源端口号和16位目的端口号。32位序号:假设第一次…

Linux驱动开发基础(Hello驱动)

所学内容来自百问网 目录 1. 文件在内核中的表示 2. 打开字符设备节点时&#xff0c;内核中也有对应的struct file 3. 编写驱动程序步骤 4. 相关知识点 4.1 涉及函数解析 4.2 module_init/module_exit的实现 4.3 register_chrdev的内部实现 4.4 class_destroy/device_…

(Jmeter、Fiddler)脚本转换Loadrunner脚本

背景:公司政治任务、各种体系文档要留档,但有些不在体系内的工具生成的脚本需要转化到体系内以备留档。 一、Loadrunner代理设置 开始录制配置: Record->Remote Application via LoadRunner Proxy LoadRrunner Proxy listens on port-> 8889 (系统建立出入站规则…

解析防蠕动交叉导轨的防蠕动机制

随着工业自动化的不断发展&#xff0c;对机械导轨系统的精度和稳定性要求越来越高。防蠕动交叉导轨作为一种新型导轨系统&#xff0c;能够有效提高设备的运行精度和稳定性&#xff0c;降低维护成本。 蠕动现象通常发生在导轨负载超出其额定范围、表面粗糙度不足或润滑不良等情况…

Python 实现 Excel 文件操作的技术性详解

目录 一、引言 二、Excel 文件格式及库的选择 2.1 Excel 文件格式 2.2 库的选择 三、安装必要的库 四、使用 openpyxl 读取 Excel 文件 4.1 基本步骤 4.2 实战案例 五、使用 pandas 读取 Excel 文件 5.1 基本步骤 5.2 实战案例 六、写入 Excel 文件 6.1 使用 …