初识--树(1)

news2024/11/17 11:41:52

下面就是这篇博客要讲的内容

    • 二叉树
  1. 树概念及结构
  2. 二叉树的概念及结构
  3. 二叉树的实现
  4. 堆的概念及运用

这篇博客主要以二叉树为主要内容。

1、树的概念及结构

1.1树的概念:

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

其中有三个注意的点:
(1)树有一个特殊的结点,称为根结点,根结点没有前驱结点
(2)除根结点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1<= i<= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继因此,树是递归定义的。
(3)树形结构中,子树之间不能有交集,否则就不是树形结构
在这里插入图片描述
在这里插入图片描述
在第一个图中A节点就是我们的根节点。

1.2树的基本概念
在这里插入图片描述

(1)结点的度:一个结点含有的子树的个数称为该结点的度; 如上图:A的为6
(2)叶结点或终端结点:度为0的结点称为叶结点; 如上图:B、C、H、I…等结点为叶结点
(3)非终端结点或分支结点:度不为0的结点; 如上图:D、E、F、G…等结点为分支结点
(4)双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点; 如上图:A是B的父结点
(5)孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点; 如上图:B是A的孩子结点
(6)兄弟结点:具有相同父结点的结点互称为兄弟结点; 如上图:B、C是兄弟结点
(7)树的度:一棵树中,最大的结点的度称为树的度; 如上图:树的度为6
(8)结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推;
(9)树的高度或深度:树中结点的最大层次; 如上图:树的高度为4
(10)堂兄弟结点:双亲在同一层的结点互为堂兄弟;如上图:H、I互为兄弟结点
(11)结点的祖先:从根到该结点所经分支上的所有结点;如上图:A是所有结点的祖先
(12)子孙:以某结点为根的子树中任一结点都称为该结点的子孙。如上图:所有结点都是A的子孙

森林:由m(m>0)棵互不相交的树的集合称为森林;

1.3树的表示

这里就简单的了解其中最常用的孩子兄弟表示法——左孩子右兄弟。

typedef int DataType;
struct Node
{
	struct Node* firstChild1;
	// 第一个孩子结点
	struct Node* pNextBrother;
	// 指向其下一个兄弟结点
	DataType data;
	// 结点中的数据域
};

这就是我们树中的一个节点。
在这里插入图片描述
表现形式如上图。
这种方式来表示树非常的牛!大家可以试想如果我们不用这种方式我们怎样来表示我们的树——
树的分支数我们知道吗?那我们怎样定义我们的分支呢?那就只有顺序表,那顺序表开多大的空间?那样会非常的麻烦,而且会浪费我们的空间,而上图的方式完美解决了我们的问题。

2、二叉树的概念及结构

2.1 二叉树的概念
在这里插入图片描述
形如上图每个节点都最多只有两个分支的数就为我们的二叉树。

2.2 特殊的二叉树

  1. 满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。
  2. 完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。
    在这里插入图片描述

2.3 二叉树的性质(非常重要,尽量自己尝试着去推导)

1、若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有(2^(i-1))个结点。
2、若规定根结点的层数为1,则深度为h的二叉树的最大结点数是2^h-1。
3、对任何一棵二叉树, 如果度为0其叶结点个数为n0 , 度为2的分支结点个数为n2 ,则有 n0= n2+1。
4、若规定根结点的层数为1,具有n个结点的满二叉树的深度,h=log(n+1)。(log以2为底)
5、对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有结点从0开始编号,则对于序号为i的结点有:

  1. 若i>0,i位置结点的双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点
  2. 若2i+1<n,左孩子序号:2i+1,2i+1>=n否则无左孩子
  3. 若2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子
    这三个推论在堆的实现、堆排序中使用,所以也希望大家能记住。
    由于篇幅原因我这里就不再给大家一步一步推了。

2.4 二叉树的存储

二叉树一般可以使用两种结构存储,一种顺序结构,一种链式结构。
(1)顺序结构

顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。
在这里插入图片描述
顺序结构有什么好处呢?
可以用下标来表示父子关系
在这里插入图片描述
(2)链式结构

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链,当前我们学习中一般都是二叉链。

typedef int BTDataType;
// 二叉链
struct BinaryTreeNode
{
struct BinTreeNode* left;
// 指向当前结点左孩子
struct BinTreeNode* right; // 指向当前结点右孩子
BTDataType data;
// 当前结点值域
}

这篇博客先了解我们的链式存储,在下一篇我们就介绍顺序存储–堆。

三、二叉树链式结构的实现

3.1 二叉树的遍历(前序、中序以及后序遍历)

学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的结点进行相应的操作,并且每个结点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。
在这里插入图片描述

按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历:

  1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。
  2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。
  3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。
    在这里插入图片描述

这里我画出来前序和中序,大家自己来画一下后序遍历,这一块可以为我们后面要学的搜索二叉树打下基础,这一块也是必须要掌握的。

遍历代码部分:

这里我们还没有学会创建我们的树,那么我们就用笨办法,手动去构建我们的树
(1)、首先我们要先确定树的形状,我这里的是自己随便画的大家可以自己来构建自己想要的树:
在这里插入图片描述
(2)代码构建:

typedef struct TreeNode
{
	int val;
	struct TreeNode* left;
	struct TreeNode* right;
}TreeNode;//二叉树的节点

TreeNode* creatTree()
{
	TreeNode* node1 = (TreeNode*)malloc(sizeof(TreeNode));
	node1->val = 1;
	node1->left = node1->right = NULL;
	
	TreeNode* node2 = (TreeNode*)malloc(sizeof(TreeNode));
	node2->val = 2;
	node2->left = node2->right = NULL;

	TreeNode* node3 = (TreeNode*)malloc(sizeof(TreeNode));
	node3->val = 3;
	node3->left = node3->right = NULL;

	TreeNode* node4 = (TreeNode*)malloc(sizeof(TreeNode));
	node4->val = 4;
	node4->left = node4->right = NULL;

	TreeNode* node5 = (TreeNode*)malloc(sizeof(TreeNode));
	node5->val = 5;
	node5->left = node5->right = NULL;

	TreeNode* node6 = (TreeNode*)malloc(sizeof(TreeNode));
	node6->val = 6;
	node6->left = node6->right = NULL;

	TreeNode* node7 = (TreeNode*)malloc(sizeof(TreeNode));
	node7->val = 7;
	node7->left = node7->right = NULL;
	//创建我们的二叉树节点
	node1->left = node2;		node1->right = node3;
	node2->left = node4;		node2->right = node5;
	node5->right = node7;		node3->right = node6;//链接我们的树
	return node1;//返回树的根节点
}

(3)、遍历我们的二叉树:

void preOrder(TreeNode* root)
{
	if (root == NULL)
		return;
	printf("%d ", root->val);
	preOrder(root->left);
	preOrder(root->right);
}
int main()
{
	TreeNode* root = creatTree();
	preOrder(root);//前序遍历
	return 0;
}
void inOrder(TreeNode* root)//中序遍历
{
	if (root == NULL)
		return;
	inOrder(root->left);
	printf("%d ", root->val);
	inOrder(root->right);
}

大家可以看到代码部分非常的简单,但大家一定要明白它是怎样执行的。

3.2 层序遍历
层序遍历:除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根结点所在层数为1,层序遍历就是从所在二叉树的根结点出发,首先访问第一层的树根结点,然后从左到右访问第2层上的结点,接着是第三层的结点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
在这里插入图片描述
层序遍历就是一层一层访问,这里只是简单的介绍,这一块我们后面才学。

四、我们学完二叉树要解决的问题

4.1 二叉树的节点个数问题

int treeSize(TreeNode* root)
{
	if (root == NULL)
		return 0;
	return treeSize(root->left) + treeSize(root->right) + 1;
}

关于这块的问题我们采用分置的思想。
节点个数:
1、根为空–0,
2、不为空–左子树+右子树+1。
这一块对于初学者确实非常的有难度,前期我们甚至可以将代码背下来。
大家需要在不断刷题后来慢慢体会。

4.2 二叉树的叶子节点个数问题

int treeLeaveSize(TreeNode* root)
{
	if (root == NULL)
		return 0;
	if (root->left == NULL && root->right == NULL)
		return 1;
	return treeLeaveSize(root->left)+ treeLeaveSize(root->right);
}

叶子节点特征:左右子树为空。
叶子:
1、根为空–0,
2、不为空–如果左子树右子树为空,就返回1。

4.3 二叉树的高度问题

int treeHeight(TreeNode* root)
{
	if (root == NULL)
		return 0;
	int left = treeHeight(root->left);
	int right = treeHeight(root->right);
	return left > right ? left + 1 : right + 1;
}

高度:
1、根为空–0,
2、不为空–左子树与右子树中大的+1;

当然还有以下问题,大家可以自己尝试去解决,大家可以自己尝试去锻炼自己分置的思想。

1、单值二叉树。
2、 检查两颗树是否相同。
3、另一颗树的子树。
4、对称二叉树。
5、二叉树的构建与销毁。

总的来说这一部分还是非常的有难度,希望大家不要放弃,通过刷题去增强自己的信心。

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

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

相关文章

C语言 - 构造类型

构造类型&#xff1a; 数据类型的分类&#xff1a; 基本类型&#xff1a;整数型&#xff1a;短整型&#xff08;short&#xff09;、整型&#xff08;int&#xff09;、长整型&#xff08;long&#xff09;、长长整型&#xff08;long long&#xff09; 浮点型&#xff1a;单…

Java | Leetcode Java题解之第336题回文对

题目&#xff1a; 题解&#xff1a; class Solution {public List<List<Integer>> palindromePairs(String[] words) {List<List<Integer>> ans new ArrayList<>();int n words.length;for (int i 0; i < n; i) {for (int j 0; j < n…

让科技党狂喜的电动车什么样,新日凯迪拉氮,你值得拥有!

这些年电动车企为了创新可以说“八仙过海&#xff0c;各显神通”&#xff0c;有的深挖智能技术开辟新赛道&#xff0c;有的狂卷性能卷出新场景。然而&#xff0c;真正触动消费者心弦的是&#xff1a;如何实实在在地提升骑行体验。正是洞察了这一核心需求&#xff0c;新日电动车…

如何进行屏幕录制?有哪些免费的录屏软件推荐?

如何进行屏幕录制&#xff1f;有哪些免费的录屏软件推荐&#xff1f; 对于内容创作者、教育工作者和游戏玩家来说。精通屏幕录制技术已成为一项不可或缺的技能&#xff01;本文将深入探讨如何使用市面上的顶级屏幕录制软件&#xff0c;例如嗨格式录屏大师和OBS Studio&#xff…

hyper-v安装window10操作系统

Hyper-V是微软的一款虚拟化产品&#xff0c;是微软第一个采用类似Vmware ESXi和Citrix Xen的基于hypervisor的技术。 目标&#xff1a;在window10的物理机上基于hyper-v运行虚拟window10。 准备条件 准备好window10操作系统&#xff0c;iso、wim、esd等都行&#xff0c;我这…

侧向开敞式通风天窗的设计特点和优势

一、特点 1、侧向开启&#xff1a;与传统的顶开型窗户相比&#xff0c;侧向开敞式通风天窗采用侧向开启的方式&#xff0c;这种设计不仅为室内提供了更大的通风面积&#xff0c;还使得空气流动更加顺畅。 2、防雨功能&#xff1a;设计时考虑防雨需求&#xff0c;能够在下雨时保…

如何在C++ QT 程序中集成cef3浏览器组件去显示网页?

目录 1、问题描述 2、为什么选择cef3浏览器组件 3、cef3组件的介绍与下载 4、将cef3组件封装成sdk 5、如何使用cef3组件加载web页面 5.1、了解CefApp与CefClient 5.2、初始化与消息循环 5.3、如何创建浏览器 5.4、重载CefClient类 6、在qt客户端集成cef组件 7、最后…

VS2022上面运行QT程序

需求&#xff1a;之前是在QT6.6上面运行&#xff0c;现在想试一下VS2022&#xff1a; 操作步骤&#xff1a; 第一步&#xff1a; 在QT的配置软件中安装MSVC 第二步&#xff1a;配置VS 第三步&#xff1a;在VS上面安装QT插件&#xff0c;但是在QT上面安装速度很慢&#xff0c;…

Leetcode面试经典150题-15.三数之和

解法都在代码里&#xff0c;不懂就留言或者私信 class Solution {/**每次做这个题都想着这事最后一次了&#xff0c;但是确实很高频&#xff0c;还是多练练吧基本思路&#xff1a;先把原来的数组按照从小到大的顺序排列&#xff0c;然后我们从头开始确定第一个数&#xff0c;然…

STM32CubeMX stm32不限长度使用DMA收发串口数据

STM32CubeMX 配置 代码 stm32h7xx_it.c /*** brief This function handles UART7 global interrupt.*/ void UART7_IRQHandler(void) {/* USER CODE BEGIN UART7_IRQn 0 */if (UART7 huart7.Instance) // 判断是否是空闲中断{if (__HAL_UART_GET_FLAG(&huart7, UART_FLA…

数据导入导出(EasyExcel)框架入门指南

写在前面 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 文章目录 EasyExcel 框架概述依赖APIExcel 实体类注解写 Excel概念介绍写 Excel 通用参数WriteWorkbookWriteSheetWriteTable 代码…

【Qt】常用控件QRadioButton

常用控件QRadioButton QRadioButton是单选按钮&#xff0c;可以在多个选项中选择一个。 作为QAbstractButton和QWidget的子类&#xff0c;其属性和用法&#xff0c;对于QRadioButton同样适用。 属性说明 checkable 是否能选中 checked 是否已经被选中. checkable 是 checked…

平安养老险宿州中支开展消防培训及逃生演练活动

近日&#xff0c;平安养老保险股份有限公司&#xff08;以下简称“平安养老险”&#xff09;宿州中心支公司邀请助安消防公司袁教官为公司员工开展消防安全知识培训。 培训教官结合近年来火灾典型案例&#xff0c;对火灾的危害、火灾的预防措施、灭火器材的使用进行深入浅出的…

centos 常用软件的安装和使用

redis 安装 0、下载、解压那些的我在这儿就不说了&#xff0c;有不懂的&#xff0c;看我之前写的博客。 1、在安装 redis 之前&#xff0c;我们得先安装它的依赖 yum install gcc-c 2、假设我下载放进的目录是 /usr/local/src/ &#xff0c; 并且 我的版本为 redis-6.0.8 …

数字化转型对金融服务业的影响

数字化转型正在塑造每个行业&#xff0c;从快速消费品到金融&#xff0c;每个行业都受到新兴技术的影响。 那么&#xff0c;数字化转型在金融服务中扮演什么角色&#xff1f;这对招聘前景有何影响&#xff1f; 我们探讨了数字化转型对该行业的影响、其对招聘策略的影响、数据…

适合大学生的耳机排行有哪些?四大TOP级性价比蓝牙耳机合集

大学生生活多彩多姿&#xff0c;耳机也成为了他们日常生活、学习和娱乐中不可或缺的配件。但面对市面上琳琅满目的耳机品牌和型号&#xff0c;选择性价比高且适合自身需求的耳机变得尤为重要&#xff0c;那么适合大学生的耳机排行有哪些&#xff1f;今天我就为大家精选了四大TO…

SpringBoot如何配置动态数据源?原理+实战

若没空探究原理可直接跳转到“实现方式&#xff1a;注解切面”目录 数据源切换方法 Spring对数据源的管理类似于策略模式&#xff0c;不懂策略模式也没关系&#xff0c;其实就是有一个全局的键值对&#xff0c;类型是Map<String, DataSource>。当JDBC操作数据库之时&am…

boot项目:程序包xxxx.xxxx.xxx不存在

你们好&#xff0c;我是金金金。 idea2021版本&#xff0c;在maven项目中运行程序的时候会出现java程序包不存在现象。(属于它的一个小bug) 场景 启动boot项目时报错如下 解决 清理缓存 重新加载所有maven项目 重新启动项目即可 测试 已测试&#xff0c;项目成功启动~ 编写有误…

代码规范 —— Redis 开发规范

优质博文&#xff1a;IT-BLOG-CN 一、开发规范 【1】弱依赖检查与线下确认&#xff1a;Redis必须是弱依赖&#xff0c;即Redis宕机不影响业务。包括超时检查。 【2】是否当存储使用检查&#xff1a;Redis不能作为存储设备来使用&#xff0c;只能作为缓存或状态等场景来使用。…

【Mudo库】实战项目之简要介绍

文章目录 前言一、效果演示二、模块1. 介绍2. 服务器模块3. 应用层模块 尾序 前言 各位C友们&#xff0c;好久不见&#xff0c;最近一个月在搞项目&#xff0c;算是半摆半学的状态吧&#xff0c;博客断更了一段时间&#xff0c;现在项目搞完了&#xff0c;博客之后也会慢慢更新…