【数据结构】C++语言实现二叉树的介绍及堆的实现(详细解读)

news2024/11/15 7:39:47

9efbcbc3d25747719da38c01b3fa9b4f.gif

 c语言中的小小白-CSDN博客c语言中的小小白关注算法,c++,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm=1001.2014.3001.5343

给大家分享一句我很喜欢我话:

知不足而奋进,望远山而前行!!!

铁铁们,成功的路上必然是孤独且艰难的,但是我们不可以放弃,远山就在前方,但我们能力仍然不足,所有我们更要奋进前行!!!

今天我们更新了二叉树内容,

🎉 欢迎大家关注🔍点赞👍收藏⭐️留言📝

首先我们为大家说一下树的概念和结构,树是一种非线性的数据结构,它是由n(n >= 0)个有限结点组成的一个具有层次关系的集合,把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的

  • 有一个特殊的结点,称为根结点,根节点没有前驱结点。
  • 除跟根结点外,其余结点被分成M(M>0)个互不相交的集合T1、T2…Tm,其中每一个集合Ti(1<=i<=m)又是一棵结构与树类似的子树。每颗子树的根节点有且只有一个前驱,可以有0个或多个后继。
  • 因此,树是递归定义的。

有关树的一些概念:

  1. 节点的度:一个节点含有的子树的个数称为该节点的度;如上图:A的为6
  2. 叶节点或终端节点:度为0的节点称为叶节点;如上图:B、C、H、I…等节点为叶节点非终端节点或分支节点:度不为0的节点;如上图:D、E、F、G…等节点为分支节点
  3. 兄弟节点:具有相同父节点的节点互称为兄弟节点;如上图:B、C是兄弟节点
  4. 树的度:一棵树中,最大的节点的度称为树的度;如上图:树的度为6
  5. 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
  6. 树的高度或深度:树中节点的最大层次;如上图:树的高度为4(有两种说法-从0开始还是从1开始,空树-1,空树0)
  7. 节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先
  8. 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙
  9. 森林:由m (m>0)棵互不相交的多颗树的集合称为森林;(数据结构中的学习并查集本质就是一个森林)——(日常很少碰到森林,并查集就是一个森林)

其中这些概念中第 4、6、7条较为重要,其余了解一下即可。

树的要求:

  • 子树是不相交的
  • 除了根结点之外,每个结点有且仅有一个父结点
  • 一个N个结点的树有N-1条边

树的表示

相对于线性表,树的结构就复杂很多了。最常用的表示方法——孩子兄弟表示法。

二叉树

与普通的树最大的不同是它最多只有两个子树。

特殊的二叉树

  1. 满二叉树:每一层都是满的。

    假设一棵满二叉树的高度是 h,那么它的总结点个数是:20+21+22+…2(h-1) =N。

    推导公式:2^h-1 = N;h = log2N+1以2位底N的对数+1。

  2. 完全二叉树

完全二叉树是个效率很高的数据结构,完全二叉树是由满二叉树引出来的。

假设树的高度是h,前h-1层是满的,最后一层不满,但是最后一层从左往右都是连续的。

最后一层最少有一个结点。

结点个数为:2^h-1-X= N,高度近似为:h = log2N+1+X以二为底N的对数+1

图有点难看不要介意

这些就是关于树的一些基本概念,下面我们来介绍一下关于树的实现。

堆的实现:

这里我们将会分为初始化、销毁、建堆、堆的删除、取出堆顶元素、判断是否为空、向上调整和向下调整这几步来完成。

头文件及堆结构的定义:

#pragma once
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<assert.h>
#include<algorithm>
#include<cmath>
#include<utility>



typedef int HPDataType;

typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}HP;

初始化:

//初始化
void HPInit(HP* php)
{
	assert(php);
	php->a = NULL;
	php->capacity = php->size= 0;

}

销毁:

void HPDestroy(HP* php)
{
	assert(php);

	free(php);
	php->a = NULL;
	php->capacity = php->size = 0;
	
}

向上调整:

//向上调整(小根堆)
void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child>0)
	{
		if (a[child] < a[parent])//小于就换就相当于建小堆
		//if (a[child] > a[parent])//大于就换就会变成大堆
		{
			std::swap(a[child], a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

建堆:

void HPPush(HP* php, HPDataType x)
{
	assert(php);

	if (php->size == php->capacity)
	{
		int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
		HPDataType* tmp = (HPDataType*)realloc(php->a,sizeof(HPDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc failed!!!");
			return;
		}
		php->a = tmp;
		php->capacity = newcapacity;
	}

	php->a[php->size++] = x;

	//向上调整
	AdjustUp(php->a, php->size - 1);
}

向下调整:

void AdjustDown(HPDataType* a, int n, int parent)
{
	//假设法
	//假设左孩子小
	int child = parent * 2 + 1;

	while(child<n)
	{
		if (child + 1 < n &&a[child + 1] < a[child])//这里如果是左孩子大于右孩子,就要再加加child
		{
			++child;
		}

		if (a[child] < a[parent])
		{
			std::swap(a[child], a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else break;
	}
	
}

删除堆顶的数据:

HPDataType HPTop(HP* php)
{
	assert(php);
	assert(php->size > 0);


	return php->a[0];
}

判空:

bool HPEmpty(HP* php)
{
	assert(php);

	return php->size == 0;
}

总代码:

TEST.c:

#include"Heap.h"


void TestHeap1()
{
	int a[] = { 4,2,8,1,5,6,7,9 };
	HP hp;
	HPInit(&hp);
	for (size_t i = 0; i < sizeof(a) / sizeof(int); i++)
	{
		HPPush(&hp, a[i]);
	}

	while (!HPEmpty(&hp))
	{
		printf("%d ", HPTop(&hp));
		HPPop(&hp);
	}


	HPDestroy(&hp);
}

void HeapSort(int* a, int n)
{
	//首先建堆
	//升序:建大堆
	//降序:建小堆
	for (int i=0;i<n;i++)
	{
		AdjustUp(a, i);
	}

	int end = n - 1;
	///这里>0即可,因为=0时只剩下最后一个,就不再需要继续进行了
	while (end>0)//思路就是:比如我们升序排序,那么我们就利用大根堆,每次都将最大的那个数放在最顶上,然后将它和最后一个交换,然后让整体的大小--,那么最后一个就不再会受影响
	{
		std::swap(a[0], a[end]);
		AdjustDown(a, end, 0);
		--end;
	}


}

void TestHeap2()
{
	int a[] = { 4,2,8,1,5,6,9,7,3,10,23,14,125 };
	HeapSort(a, sizeof(a) / sizeof(0));

	for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
	{
		std::cout << a[i] << " ";
	}
}

int main()
{
	TestHeap2();

	return 0;
}

Heap.c:

#include"Heap.h"


//初始化
void HPInit(HP* php)
{
	assert(php);
	php->a = NULL;
	php->capacity = php->size= 0;

}


//销毁
void HPDestroy(HP* php)
{
	assert(php);

	free(php);
	php->a = NULL;
	php->capacity = php->size = 0;
	
}


//向上调整(小根堆)
void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child>0)
	{
		if (a[child] < a[parent])//小于就换就相当于建小堆
		//if (a[child] > a[parent])//大于就换就会变成大堆
		{
			std::swap(a[child], a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}



//建堆
void HPPush(HP* php, HPDataType x)
{
	assert(php);

	if (php->size == php->capacity)
	{
		int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
		HPDataType* tmp = (HPDataType*)realloc(php->a,sizeof(HPDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc failed!!!");
			return;
		}
		php->a = tmp;
		php->capacity = newcapacity;
	}

	php->a[php->size++] = x;

	//向上调整
	AdjustUp(php->a, php->size - 1);
}

//向下调整
void AdjustDown(HPDataType* a, int n, int parent)
{
	//假设法
	//假设左孩子小
	int child = parent * 2 + 1;

	while(child<n)
	{
		if (child + 1 < n &&a[child + 1] < a[child])//这里如果是左孩子大于右孩子,就要再加加child
		{
			++child;
		}

		if (a[child] < a[parent])
		{
			std::swap(a[child], a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else break;
	}
	
}

//删除堆顶的数据
void HPPop(HP* php)
{
	assert(php);
	assert(php->size > 0);
	std::swap(php->a[0], php->a[php->size - 1]);//就是将第一个与最后一个换掉,然后将他们向下调整,
	php->size--;//直接size--删去最后一个元素

	AdjustDown(php->a, php->size, 0);
}



//取出堆顶数据
HPDataType HPTop(HP* php)
{
	assert(php);
	assert(php->size > 0);


	return php->a[0];
}



bool HPEmpty(HP* php)
{
	assert(php);

	return php->size == 0;
}

Heap.h:

#pragma once
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<assert.h>
#include<algorithm>
#include<cmath>
#include<utility>



typedef int HPDataType;

typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}HP;

//初始化
void HPInit(HP* php);


//销毁
void HPDestroy(HP* php);


//建堆
void HPPush(HP* php,HPDataType x);

//堆的删除
void HPPop(HP* php);

//取出堆顶数据
HPDataType HPTop(HP* php);

bool HPEmpty(HP* php);

void AdjustUp(HPDataType* a, int child);
void AdjustDown(HPDataType* a, int n, int parent);

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

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

相关文章

蓝桥杯-外卖店优先级(简单写法)

“饱了么”外卖系统中维护着 N 家外卖店&#xff0c;编号 1∼N。 每家外卖店都有一个优先级&#xff0c;初始时 (0 时刻) 优先级都为 0。 每经过 1 个时间单位&#xff0c;如果外卖店没有订单&#xff0c;则优先级会减少 1&#xff0c;最低减到 0&#xff1b;而如果外卖店有订…

AWS简介

AWS AWS&#xff0c;全称为Amazon Web Services&#xff0c;是亚马逊公司旗下的云计算服务平台&#xff0c;自2006年起向全球用户提供广泛而深入的云计算服务。AWS是全球最全面、应用最广泛的云平台之一&#xff0c;它从全球的数据中心提供超过200项功能齐全的服务&#xff0c…

类和对象的特性

1.检查错误。 代码&#xff1a; #include <iostream>using namespace std;class Time { private:/* data */ public:Time(/* args */);~Time();void set_time(void);void show_time(void);int hour;int minute;int sec; };Time::Time(/* args */) { }Time::~Time() { }T…

打个样为centos安装mysql(下载安装)

文章目录 一、下载二、卸载mariadb三、创建用户和组四、解压并安装mysql五、修改my.cnf六、配置环境七、初始化数据库八、启动mysql服务、改密码配置远程链接九、完成 如果是windows的服务器&#xff0c;请看我另外一个文章&#xff1a; windows下安装mysql教程 一、下载 htt…

rocketmq的存储和检索

messageId是rocketmq自动生成的。

通用人工智能将如何重塑未来

通用人工智能(AGI)是一种人工智能&#xff0c;具有与人类一样的获取知识、应用知识解决问题和理解能力。与专门处理受限任务的狭义人工智能系统不同&#xff0c;AGI寻求发展先进的认知技能&#xff0c;以促进在不同情况下完成复杂任务。AGI是一种人工智能&#xff0c;试图模仿人…

Linux网络编程——HTTP协议的理解与运用

目录 前言 一、认识URL 二、认识HTTP样例 三、HTTP的报头内容 1.url 2. Content-Type 3.Method 方法 1.GET方法 2.POST方法 4、状态码 5.cookie和session 前言 我们知道&#xff0c;协议就是一种约定&#xff0c;客户端与服务端统一的用这种约定进行传输数据。我们…

电工能混到这份上

最近看到某电工师傅发了一篇帖子&#xff0c;大致内容是他在处理一个简单故障的时候居然花了很长的时间。我们一起来看看他遇到的是什么故障吧! plc 控制的一台设备&#xff0c;行走部分靠 2 个脚踏开关控制&#xff08;内部开关量控制方向&#xff0c;电位器控制速度&#xff…

PSAI超强插件来袭:一键提升设计效率!

无需魔法&#xff0c;直接在PS中完成图生图、局部重绘、线稿上色、无损放大、扩图等操作。无论你是Windows还是Mac用户&#xff0c;都能轻松驾驭这款强大的AI绘图工具&#xff0c;这款PSAI插件让你的设计工作直接起飞&#xff01; 在之前的分享中&#xff0c;我为大家推荐过两…

威纶通触摸屏下载项目文件后,文本都变成了框框的解决办法

威纶通触摸屏下载项目文件后,文本都变成了框框的解决办法 我们在用Easy builder pro编辑某些项目的情况下,编译没问题,为什么下载到触摸屏之后,文本都变成了框框了呢? 分析:: 不能正常显示文本的原因是字体文件缺失。 解决办法: 如下图所示,在Easy builder pro软件中,…

函数栈帧的创建和销毁(详细理解)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;c语言课程学习 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 问题&#xff1a; 1.ebp&#xff0c;esp两个寄存器用来维护函数栈帧 2.main函数也一个函数&#…

ArcGIS10.X入门实战视频教程(arcgis入门到精通)

点击学习&#xff1a; ArcGIS10.X入门实战视频教程&#xff08;GIS思维&#xff09;https://edu.csdn.net/course/detail/4046?utm_sourceblog2edu 点击学习&#xff1a; ArcGIS10.X入门实战视频教程&#xff08;GIS思维&#xff09;https://edu.csdn.net/course/detail/404…

C++入门系列-赋值运算符重载

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 赋值运算符重载 运算符重载 C为了增强代码的可读性引入了运算符重载&#xff0c;运算符重载是具有特殊函数名的函数&#xff0c;也具有其返回值类型&#xff0c;函数名字以及参…

(2)双指针练习:复写零

复写零 题目链接&#xff1a;1089. 复写零 - 力扣&#xff08;LeetCode&#xff09; 给你一个长度固定的整数数组 arr &#xff0c;请你将该数组中出现的每个零都复写一遍&#xff0c;并将其余的元素向右平移。 注意&#xff1a;请不要在超过该数组长度的位置写入元素。请对输入…

想做好抖店?新手、老玩家切勿掉进这些坑,操作要慎重!

大家好&#xff0c;我是电商花花。 很多人都说做抖音小店不需要脑子&#xff0c;会抄就行&#xff0c;难道做店真的就是这样吗&#xff1f; 真的就是会抄&#xff0c;会简单选品&#xff0c;找一些达人就能出单&#xff0c;就能实现睡后收入了吗&#xff1f; 其实并不见得&a…

✅HTTPS和HTTP的区别是什么?

一、问题解析 HTTP和HTTPS是两种协议&#xff0c;分别是Hypertext Transfer Protocol和HyperText Transfer Protocol Secure。 HTTPS还经常被称之为HTTP over SSL或者HTTP over TSL&#xff0c;HTTPS经由HTTP进行通信&#xff0c;但利用SSL/TLS来加密数据包。 他们的区别主要…

【35分钟掌握金融风控策略28】贷中模型体系策略应用

目录 贷中模型体系策略应用 信用模型体系和模型在策略中的应用 反欺诈模型体系和模型在策略中的应用 运营模型体系和模型在策略中的应用 贷中模型体系策略应用 在贷前模型部分已经讲过&#xff0c;贷前开发的很多模型是可以在贷中直接使用的。贷中与贷前的不同点在于&…

三大平台直播视频下载保存方法

终于解决了视频号下载的问题&#xff0c;2024年5月15日亲测可用。 而且免费。 教程第二部分&#xff0c;有本地电脑无法下载的解决方案。 第一部分&#xff1a;使用教程&#xff08;正常&#xff09; 第1步&#xff1a;下载安装包 下载迅雷网盘搜索&#xff1a;大海福利合集…

建模:3dmax

3Dmax 制作模型和动画&#xff08;橘肉&#xff09;&#xff1b; RizomUV 对模型进行展UV&#xff08;橘皮&#xff09;&#xff1b; Substance Painter 纹理手绘&#xff08;给橘皮制定想要的皮肤&#xff09;&#xff1b; 1.基础 1.1可编辑多边形、可编辑样条线 体、面都需要…

【计算机毕业设计】springboot二手家电管理平台

时代在飞速进步&#xff0c;每个行业都在努力发展现在先进技术&#xff0c;通过这些先进的技术来提高自己的水平和优势&#xff0c;二手家电管理平台当然不能排除在外。二手家电管理平台是在实际应用和 软件工程的开发原理之上&#xff0c;运用java语言以及前台VUE框架&#xf…