二叉树及其链式结构

目录

一:树概念及结构

1.树的概念

2.树的相关概念

 3.树的表示

 二:二叉树的概念及结构

 1.概念

 2.特殊的二叉树

<1>. 满二叉树:

<2>. 完全二叉树:

3.二叉树的性质

4.二叉树的存储结构

<1>.顺序结构

<2>.链式结构

5.链式二叉树的实现

<1>:二叉树的前序遍历

<2>.二叉树的中序遍历

<3>.二叉树的后序遍历

<4>.二叉树的节点个数

<5>.二叉树的叶子节点的个数

<6>.二叉树的高度

<7>.二叉树第k层节点个数

<8>.二叉树查找值为x的节点

<9>.二叉树销毁

<10>.通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树


一:树概念及结构

1.树的概念


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

2.树的相关概念

80791be6c40b42ec962970dc92e6a84b.png


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

 3.树的表示

双亲表示法,
孩子表示法、
孩子双亲表示法
孩子兄弟表示法(常用).......
typedef int DataType;
struct Node
{
struct Node* firstChild; // 第一个孩子结点
struct Node* pNextBrother; // 指向其下一个兄弟结点
DataType _data; // 结点中的数据域
};

 画图表示:

88e1bdb385a446c1acb8eee1a93fa344.png

 二:二叉树的概念及结构

 1.概念


一棵二叉树是结点的一个有限集合,该集合:
1. 或者为空

2. 由一个根节点加上两棵别称为左子树和右子树的二叉树组成

7ad74b0b75fe48ca84338a38a8b68361.png

<1>. 二叉树不存在度大于2的结点
<2>. 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树
其可能存在的特殊情况:空树 ; 只有根节点 ; 只有左子树 ; 只有右子树 ; 左右子树均存在。
再图形中表示如下图:
ee289ea92c2849dc86ebaae184d1737e.png

 2.特殊的二叉树

<1>. 满二叉树:

一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为H,且结点总数是 2^ H - 1,则它就是满二叉树。

ffea04af5ead473fa77e60a7feeb8509.png

<2>. 完全二叉树:

完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K 的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对 应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。
73227a82b65b418ea1fd52434bbc1250.png

 3.二叉树的性质


1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有 2^(i-1)个结点.

 2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是 2^h - 1。

3. 对任何一棵二叉树, 如果度为0其叶结点个数为n0 , 度为2的分支结点个数为 ,则有n0= n2+1

9ca3db06a47a4f57a20ef76f35ac1764.png

4.若规定根节点的层数为1,具有n个结点的满二叉树的深度:

h = log2  (n+1) --- 以2为底,n+1的对数。

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否则无右孩子

4.二叉树的存储结构

<1>.顺序结构

顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空 间的浪费。而现实中使用中只有堆才会使用数组来存储。
二叉树顺 序存储在物理上是一个数组,在逻辑上是一颗二叉树。

a9814f1502e44b96a2fa23260dc79d03.png

<2>.链式结构


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

5.链式二叉树的实现


在此处,我们先手动创建一个二叉树,链式二叉树,可以开辟节点,然后自己进行链接:

//链式二叉树

typedef char BTDataType;

typedef struct BinaryTreeNode
{
    BTDataType _data;
    struct BinaryTreeNode* _left;
    struct BinaryTreeNode* _right;
}BTNode;

BTNode* BuyNode(BTDataType x)
{
    //开辟结点
    BTNode* node = (BTNode*)malloc(sizeof(BTNode));
    if (node == NULL)
    {
        perror("malloc fail\n");
        return NULL;
    }
    node->_data = x;
    node->_left = NULL;
    node->_right = NULL;

    return node;

}
BTNode* CreaBinaryTree()
{
    BTNode* node1 = BuyNode('a');
    BTNode* node2 = BuyNode('b');
    BTNode* node3 = BuyNode('c');
    BTNode* node4 = BuyNode('d');
    BTNode* node5 = BuyNode('e');
    BTNode* node6 = BuyNode('f');
    BTNode* node7 = BuyNode('g');
    BTNode* node8 = BuyNode('h');

    //进行链接 --- 二叉树
    node1->_left = node2;
    node1->_right = node3;
    node2->_left = node4;
    node2->_right = node5;
    node3->_left = node6;
    node3->_right = node7;
    node4->_left = node8;

    return node1;

}

<1>:二叉树的前序遍历


前序:根、左子树、右子树

void BinaryTreePrevOrder(BTNode* root);


在自己进行链接时,开辟了:a b c d e f g h 几个节点,其链接后的图形为:

d94ff0ff22af4adf88925727a1cdd187.png

代码为:

// 二叉树前序遍历 
//前序遍历 --- 根,左子树,右子树
void BinaryTreePrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	printf("%c ", root->_data);

	BinaryTreePrevOrder(root->_left);
	BinaryTreePrevOrder(root->_right);

}

程序运行成功后:

3b911e7d8735493aa22905c7bf2944e2.png

 画图验证:

1bc86b2972d3443893f2e3496292b0ef.png

在此处我们仅画出了,左半部分的递归展开图

画到了(a b d h N N N e N N ),右边部分由于空间不够原因,不在展开画出。

<2>.二叉树的中序遍历


中序:左子树、根、右子树

void BinaryTreeInOrder(BTNode* root);


代码为:

// 二叉树中序遍历
//中序遍历 --- 左子树,根,右子树
void BinaryTreeInOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	BinaryTreeInOrder(root->_left);

	printf("%c ", root->_data);
	BinaryTreeInOrder(root->_right);

}

运行效果为:

画递归展开图表示:

<3>.二叉树的后序遍历


后序:左子树、右子树、根

void BinaryTreePostOrder(BTNode* root);


代码为:

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	BinaryTreeInOrder(root->_left);
	BinaryTreeInOrder(root->_right);
	printf("%c ", root->_data);

}

运行效果为:

 画递归展开图表示:

尝试画简单的递归展开图 --- 在二叉树上画图表示出来:

<4>.二叉树的节点个数


void BinaryTreeSize(BTNode* root);


若节点为空,则返回0。

否则,返回左子树的节点个数 + 右子树的节点个数 + 1

代码为:

// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;
}

运行效果为:

 画函数递归展开图:

<5>.二叉树的叶子节点的个数


叶子节点 --- 度为 0 的节点。

void BinaryTreeLeafSize(BTNode* root);


若节点为空,则返回 0 ;

若节点的( 左/右 )节点都为空,即该节点的度为 0 ,为叶子节点,返回1;

然后计算左子树和右子树的叶子节点个数。

代码为:

// 二叉树叶子节点个数
//叶子节点 --- 度为0的节点
int BinaryTreeLeafSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	if (root->_left == NULL && root->_right == NULL)
	{
		return 1;
	}
	return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}

运行效果为:

 根据构建的 二叉树可知,该二叉树的叶子节点为 4 

<6>.二叉树的高度


int BTreeHeight(BTNode* root);

//存在领导不记事的情况


代码为:

//二叉树的高度
int BTreeHeight(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	//领导不记事,当树特别大的时候,会超出时间限制。 --- 应将所得数据保存下来
	//return  BTreeHeight(root->_left) > BTreeHeight(root->_right) ? BTreeHeight(root->_left) + 1 : BTreeHeight(root->_right) + 1;

	int LeftHeight = BTreeHeight(root->_left);
	int RightHeight = BTreeHeight(root->_right);
	return LeftHeight > RightHeight ? LeftHeight + 1 : RightHeight + 1;
	//加1加的是根节点
}

运行效果为:

通过观察可以得知,我们所创建的二叉树为4层,故二叉树的高度为4。

<7>.二叉树第k层节点个数


int BinaryTreeLevelKSize(BTNode* root, int k);

//我们需要通过第 k - 1 层,来判定第 k 层


代码为:

// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	assert(k>0);// k 值必须为大于0的有效值
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	return BinaryTreeLevelKSize(root->_left, k - 1) 
		+ BinaryTreeLevelKSize(root->_right, k - 1);
}

运行效果为:

 第三层有四个

 第四层有一个

画递归展开图进行分析:

<8>.二叉树查找值为x的节点


BTNode* BinaryTreeFind(BTNode* root, BTDataType x);


代码为:

// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->_data == x)
	{
		return root;
	}
	BTNode* ret1 = BinaryTreeFind(root->_left, x);
	if (ret1)
	{
		return ret1;
	}
	BTNode* ret2 = BinaryTreeFind(root->_right, x);
	if (ret2)
	{
		return ret2;
	}
	return NULL;
}

运行效果为:

----  可以找到的情况

 ---- 不可以找到的情况

<9>.二叉树销毁


void BinaryTreeDestory(BTNode** root);


代码为:

// 二叉树销毁
void BinaryTreeDestory(BTNode** root)
{
	if ((*root) == NULL)
	{
		return;
	}
	BinaryTreeDestory(&(*root)->_left);//BTNode ** root 
	BinaryTreeDestory(&(*root)->_right);
	free(*root);
	//在此处进行置空(NULL),对外面没有作用
	//可以自己在函数调用后进行置空操作
}

运行结果为:

---- 程序正确结束

<10>.通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树


 BTNode* BinaryTreeCreate(BTDataType* a, int* pi);

// pi --- 数组下标

//若 a[*pi] == '#' ,数组下标 + 1 ,并且返回空


 代码为:

BTNode* BinaryTreeCreate(BTDataType* a, int* pi)
{
	if (a[*pi] == '#')
	{
		(*pi)++;//数组下标 +1
		return NULL;
	}

	BTNode* root = BuyNode(a[*pi]);//开辟节点
	(*pi)++;

	//进行链接
	root->_left = BinaryTreeCreate(a, pi);
	root->_right = BinaryTreeCreate(a, pi);

	return root;
}

 运行效果为:

 画图表示:

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

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

相关文章

渗透专题丨web Top10 漏洞简述(2)

文件包含漏洞 1、漏洞简述 程序在引用文件的时&#xff0c;引用的文件名&#xff0c;用户可控的情况&#xff0c;传入的文件名校验不严&#xff0c;从而操作了预想之外的文件&#xff0c;就有可能导致文件泄漏和恶意的代码注入。这是因为程序开发时候会把重复使用的函数写到归…

[笔记]pg常用命令

数据库版本 &#xff1a;9.6.6 注意 &#xff1a;PostgreSQL中的不同类型的权限有SELECT,INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER,CREATE,CONNECT,TEMPORARY,EXECUTE 和 USAGE。 1. 登录PG数据库 以管理员身份 postgres 登陆&#xff0c;然后通过 #psql -U postg…

新世界-旧世界

以下内容是这两天朋友问答形成的一些观点&#xff0c;堆成一篇文章。看似没有关联性&#xff0c;但你仔细品味&#xff0c;你会感觉到它们其实讲的是一个事。至于是一个啥事&#xff0c;我不说&#xff0c;你们自己猜。 &#xff08;1&#xff09; 今年年初看见篇文章&#xff…

mdBook介绍及使用——使用 Markdown 创建你自己的博客和电子书

目录 介绍一、下载与创建项目1.下载2.初始化3.结构说明 二、编写文章与启动1.编写文章2.构建3.启动 mdbook 服务 三、其他配置 介绍 mdBook 是一个使用 Markdown 创建书籍的命令行工具。它非常适合创建产品或 API 文档、教程、课程材料或任何需要清晰、易于导航和可定制的演示…

Spring中如何获取Bean方法上的自定义注解

文章目录 背景描述场景复现问题追踪解决方案扩展思考 背景描述 项目中需要扫描出来所有 标注了自定义注解A的Service里面标注了自定义注解B的方法 来做后续处理。 基本的思路就是通过Spring提供的ApplicationContext#getBeansWithAnnotation反射 来实现。 但是&#xff0c;随…

QT C++入门学习(2) QT Creator写一个简单的上位机控制LED

上位机和下位机的概念 上位机&#xff1a;指的是可以直接发送操作指令的计算机或者单片机&#xff0c;一般提供用户操作交互界面并向用户展示反馈数据。 典型设备&#xff1a;电脑、平板、手机、面板、触摸屏 下位机&#xff1a;指的是与机器相连接的计算机或者单片机&#…

SpringBoot+Vue 车辆充电桩系统

文章目录 1、效果演示效果图技术栈 2、 前言介绍&#xff08;完整源码请私聊&#xff09;3、主要技术3.4.1 数据库概念结构设计3.4.2 数据库具体设计 4 系统功能的具体实现4.1 前台功能模块4.1.1 首页功能4.1.2 用户后台管理 4.2 后台功能模块4.2.1 管理员功能4.2.2 维修员功能…

SciencePub学术 | 计算机类重点SCIEI征稿中

SciencePub学术 刊源推荐: 计算机类重点SCI&EI征稿中&#xff01;影响因子高&#xff0c;对国人非常友好。信息如下&#xff0c;录满为止&#xff1a; 一、期刊概况&#xff1a; 计算机类重点SCI&EI &#x1f4cc;【期刊简介】IF&#xff1a;7.5-8.0&#xff0c;JCR…

前端vue仿京东天猫简单好用的瀑布流瀑布流式布局列表组件waterfall

前端vue仿京东天猫简单好用的瀑布流瀑布流式布局列表组件waterfall&#xff0c; 下载完整代码请访问uni-app插件市场址:https://ext.dcloud.net.cn/plugin?id13046 效果图如下&#xff1a; #### 使用方法 使用方法 <!-- proList: 条目数组数据 goProDetail:条目点击事…

微信小程序基础使用

微信小程序的基本使用 微信小程序文件类型 微信小程序主要提供了 4 种文件类型&#xff1a; 类型名称作用是否必须存在.wxml用于页面的布局结构&#xff0c;相当于网页中 .html 文件是.wxss用于页面的样式&#xff0c;相当于网页中的 .css 文件否.js用于页面的逻辑是.json用…

1.8C++流提取运算符重载

C流提取运算符重载 在 C中&#xff0c;流提取运算符&#xff08;>>&#xff09;是用于从流中提取数据的运算符。 C中的流提取运算符可以被重载&#xff0c;使得程序员可以自定义输入对象的方式&#xff0c;更方便地输入自定义的数据类型&#xff0c;也可以使得输入更加…

数字中国,开鸿见日

讲个小故事&#xff0c;《晋书乐广传》记载&#xff0c;西晋名士乐广&#xff0c;请大文学家潘岳替自己写一篇文章。潘岳让乐广把意思完完整整告诉他&#xff0c;再由他来动笔&#xff0c;最终写成了名扬当时的《呈太尉辞河南尹表》。时人看过这篇文章&#xff0c;评价乐广是“…

传输平台太多?难以管理?看这款跨网传输系统怎样解决

传输作为企业正常运行中最日常的行为&#xff0c;也意味着出现频率最高。微信、QQ、邮件、或是钉钉等办公软件&#xff0c;每天大家上班时开着各种软件&#xff0c;进行着不同的信息交互与传输。很多员工在工作时往往是哪个软件方便顺手就用哪个传输&#xff0c;但是这样也意味…

python打包后报错,无法启动,电脑缺少api-ms-win-core-path-11-1-0.dll

参考&#xff1a;《运行打包python程序时报&#xff1a;无法启动此程序&#xff0c;因为计算机中丢失 api-ms-win-core-path-l1-1-0.dll 尝试重新安装该程序以解决此问题。》 原因&#xff1a;python版本较高&#xff0c;打包时的python版本是python3.10&#xff0c;而运行打包…

xxl-job核心源码解析

xxl-job源码解析 如何自研一个xxljob 注册服务调度服务RPC组件(基建&#xff0c;底层严重依赖)日志服务告警服务 系统架构 执行流程 各大调度中心对比 1&#xff09;服务端启动流程 首先找到配置类 XxlJobAdminConfig 可以发现该类实现 InitializingBean接口&#xff0c;…

批量生成,本地推理,人工智能声音克隆框架PaddleSpeech本地批量克隆实践(Python3.10)

云端炼丹固然是极好的&#xff0c;但不能否认的是&#xff0c;成本要比本地高得多&#xff0c;同时考虑到深度学习的训练相对于推理来说成本也更高&#xff0c;这主要是因为它需要大量的数据、计算资源和时间等资源&#xff0c;并且对超参数的调整也要求较高&#xff0c;更适合…

熬夜三晚之深度解析DuckDB MetaPipeline

深度解析DuckDB MetaPipeline 深度解析DuckDB MetaPipeline 1.导语 2.基础理论 3.HashJoin深度解析 3.1 RESULT_COLLECTOR 3.2 PROJECTION 3.3 HASH_JOIN 4.Ready 4.1 翻转 4.2 MetaPipeline与pipeline 5.汇总 1.导语 DuckDB 是…

深入理解深度学习——Transformer:基础知识

分类目录&#xff1a;《深入理解深度学习》总目录 相关文章&#xff1a; 作为当下最先进的深度学习架构之一&#xff0c;Transformer被广泛应用于自然语言处理领域。它不单替代了以前流行的循环神经网络(recurrent neural network, RNN)和长短期记忆(long short-term memory, …

从 Google 删库,到蚂蚁跑路,Care 与 Fear 点燃的 Flare

Bytebase 第一次完成融资后写了一篇文章&#xff0c;主要讲了从行业层面做 Bytebase 的逻辑。一年过去了&#xff0c;这一年我们所处的开源/infra/数据库/企业服务赛道从热点归于平静&#xff0c;尤其在国内&#xff0c;又习惯性地反应过度&#xff0c;直接降到冰点。但从全球来…

Apache RocketMQ RCE漏洞复现(CVE-2023-33246)

RocketMQ RocketMQ是阿里巴巴在2012年开发的分布式消息中间件&#xff0c;专为万亿级超大规模的消息处理而设计&#xff0c;具有高吞吐量、低延迟、海量堆积、顺序收发等特点。它是阿里巴巴双十一购物狂欢节和众多大规模互联网业务场景的必备基础设施。 漏洞概述 在其5.1.0版…