【数据结构】(二叉树)计算结点|叶子结点|高度|第K层结点数

 

目录

概念:

特殊的二叉树

二叉树的性质

二叉树的存储结构

二叉树的创建

二叉树遍历 

前序:

中序:

后序:

 计算结点数

计算叶子结点数

计算树的高度(深度)

计算第K层结点数


 

概念:

一颗二叉树是结点的一个有限集合,该集合:

1.或者为空;

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

注:

1. 二叉树不存在度大于2的结点

2. 二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

 

特殊的二叉树

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

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

注:满二叉树是一种特殊的完全二叉树。

二叉树的性质

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

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

3. 对任何一棵二叉树, 如果度为0其叶结点个数为n0 , 度为2的分支结点个数为n2 ,则有n0 =n2 +1
4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度h = log2(n+1); (是以2为底数,(n+1)为对数)

二叉树的存储结构

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

1. 顺序存储 :

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

二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。 

2. 链式存储 :

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是 链表中每个结点由三个域组成,数据域和左右指针域;

左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。

 

顺序存储在 【数据结构】——堆|Top-k|堆排序-CSDN博客

本节着重介绍链式存储;

二叉树的创建

作者水平有限,目前只能手动创建一颗伪二叉树 

 创建链表结构


typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType data;				//数据域
	struct BinaryTreeNode* left;	//左子树
	struct BinaryTreeNode* right;	//右子树
}TreeNode;

手动快速创建一个二叉树 

//创建一个结点
TreeNode*  BuyTreeNode(BTDataType x)
{
	TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
	 assert(node);
	 node->data = x;
	 node->left = NULL;
	 node->right = NULL;

	 return node;
}

// 构建树
TreeNode* CreateTree()
{
	TreeNode* node1 = BuyTreeNode(1);
	TreeNode* node2 = BuyTreeNode(2);
	TreeNode* node3 = BuyTreeNode(3);
	TreeNode* node4 = BuyTreeNode(4);
	TreeNode* node5 = BuyTreeNode(5);
	TreeNode* node6 = BuyTreeNode(6);
	TreeNode* node7 = BuyTreeNode(7);


	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;

	//增加一个结点
	//node5->right = node7;

	//返回根结点
	return node1;
}

 

二叉树遍历 

二叉树遍历分为:前序,中序,后序遍历;

前序:访问根结点的操作发生在遍历其左右子树之前

中序:访问根结点的操作发生在遍历其左右子树中间

后序:访问根结点的操作发生在遍历其左右子树之后

注:为了理解透彻,访问到NULL才结束子树的遍历

前序:

 前序遍历是先访问根节点,再访问左子树,左子树根结点访问完后 才会访问左子树结点然后右子树结点;

void PrevOrder(TreeNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	//前序
	printf("%d ", root->data);
	PrevOrder(root->left);
	PrevOrder(root->right);
}

N表示NULL,方便理解 

 

中序:

先行访问左子树,只有左子树访问完后才会访问子树根节点

void PrevOrder(TreeNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	//中序
	PrevOrder(root->left);
	printf("%d ", root->data);
	PrevOrder(root->right);

}

 

后序:

void PrevOrder(TreeNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	//后序
	PrevOrder(root->left);
	PrevOrder(root->right);
	printf("%d ", root->data);

}

 计算结点数

 递归的核心思想是: 1.子问题分治,

                2.返回条件(递归条件);

1.子问题分治:计算这棵树的结点数,可以理解 左子树结点数+右子树结点数 + 根节点;

左子树结点数又可以分为 左子树结点数+右子树结点数 +子树根节点;

右子树同理;

如何结束递归循环呢?

2.返回条件:遇到结点为NULL, 

 

//计算树的结点数
int TreeSize(TreeNode* root)
{
	if (root == NULL)
		return 0;
	return ((TreeSize(root->left) + TreeSize(root->right)) + 1);
}

计算叶子结点数

叶子结点:没有左右子树的结点;

1.分治:左子树叶子结点数+右子树结点数;

2.返回条件: 如果结点为NULL,返回0;

       如果该结点左右子树为NULL,返回1;

否则往下寻找 直至遇到返回条件;

 

 

//计算叶子结点数
int TreeLeafSize(TreeNode* root)
{
	//空 返回0
	if (root == NULL)		
		return 0;
	//结点  返回1
	if (root->left == NULL && root->right == NULL)
		return 1;
	//非空 非结点, 说明下面还有结点   左子树+右子树
	return TreeLeafSize(root->left)
			+ TreeLeafSize(root->right);
}

计算树的高度(深度)

1.分治:计算左右子树的高度,选择较大数+1 ;

2.递归条件:只有遇到NULL,就表明到该子树尾;

 

 

注:三目比较法会造成极大的负担,因为比较大小后,程序并没有记住较大值是多少,会重复访问; 

//计算树的高度
int TreeHeight(TreeNode* root)
{
	if (root == NULL)
		return 0;
	//return (TreeHeight(root->left) > TreeHeight(root->right) ? TreeHeight(root->left) : TreeHeight(root->right)) + 1;
	return fmax(TreeHeight(root->left),
			 TreeHeight(root->right)) + 1;
}

计算第K层结点数

计算第K层,相当于计算子树的第K-1层;

注:当K == 1时,要确保该结点存在,所以先行判断结点是否存在,再判断K是否等于1

 

 


//计算第K层的结点树
int TreeLevelK(TreeNode* root, int k)
{
	assert(k > 0);
	if (root == NULL)
		return 0;
	if (k == 1)
		return 1;
	return (TreeLevelK(root->left, k - 1) +
		TreeLevelK(root->right, k - 1));
}

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

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

相关文章

GPT-4V with Emotion:A Zero-shot Benchmark forMultimodal Emotion Understanding

GPT-4V with Emotion:A Zero-shot Benchmark forMultimodal Emotion Understanding GPT-4V情感:多模态情感理解的zero-shot基准 1.摘要 最近,GPT-4视觉系统(GPT-4V)在各种多模态任务中表现出非凡的性能。然而,它在情感识别方面的功效仍然是个问题。本文定…

AWS-WAF-CDN基于速率rate的永久黑名单方案(基于lambda实现)

参考方案(有坑), 所以产生了这篇博客: 点击跳转 1. 部署waf (有则跳过) 必须存在一个rate速率规则,后面的方案堆栈要用 新建rate速率规则 关联cdn资源 2.部署堆栈 (美国东部 (弗吉尼亚北部 …

【QT】QDockWidget控件的使用

目录 1.概述 2.常用函数介绍 3.QDockWidget布局相关 4.QDockWidget的使用注意事项 5.使用场景 6.简单应用示例代码 1.概述 QDockWidget类提供了一个小部件,可以停靠在QMainWindow中,也可以作为桌面上的顶级窗口浮动。 QDockWidget提供了dock Widg…

Github 2023-12-18 开源项目周报 Top14

根据Github Trendings的统计,本周(2023-12-18统计)共有14个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量TypeScript项目4Python项目4Jupyter Notebook项目3非开发语言项目1JavaScript项目1Rust项目1Go项目1 基于项目…

下载svn client,小乌龟

给兄弟们提供一个下载svn client的软件连接 不好用包退货 https://sourceforge.net/projects/tortoisesvn/ 点击download即可

21.三层链路聚合

三层链路聚合 交换机默认的接口模式为二层接口模式 1.先将交换机的接口改为三层模式 2.创建三层链路聚合端口组3 3.将端口加入链路聚合端口组3 4.给聚合后的端口配置IP地址 在路由器上也做链路聚合的操作 1.创建三层链路聚合端口组3 2.将端口加入链路聚合端口组3 …

基于ssm的航班订票管理系统论文

摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对航班订票信息管理混乱,出错率高,信息安全性差…

Git账户密码http方式的配置

Git账户密码http方式的配置 入门 git在提交时每次都需要输入密码和账号信息,可以将账号和密码进行持久化存储, 当git push的时候输入一次用户名和密码就会被记录, 不需要每次输入,提高效率,进行一下配置&#xff1…

2024年完整湖北等保测评机构名单看这里!

等保测评机构是指经公安部认证的具有资质的测评机构,主要从事等级测评活动。一般过等保需要找正规具有资质的等保测评机构。那你知道2024年湖北等保测评机构有哪些?名单有吗? 2024年完整湖北等保测评机构名单看这里! 1、湖北星…

端口占用命令 netstat (centos)+netstat (windows)

linux 1.使用 netstat 命令查看端口占用情况 netstat -tlnp 使用 -p 选项查看进程信息。 使用 -t 选项列出 TCP 协议的连接:类似(使用 -u 选项列出 UDP 协议的连接:) 2.查找占用指定端口号的应用信息 netstat -tlnp | grep 3…

Java智慧工地数字化云平台源码(SaaS模式)

智慧工地是智慧城市理念在建筑工程行业的具体体现,智慧工地解决方案是建立在高度信息化基础上一种支持人事物全面感知、施工技术全面智能、工作互通互联、信息协同共享、决策科学分析、风险智慧预控的新型信息化手段。围绕人、机、料、法、环等关键要素,…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)更改应用图标

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)更改应用图标 一、操作环境 操作系统: Windows 10 专业版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、更改图标 图标的位置:entry->src->main->resources->-b…

瑞芯微RV1103与FPGA图像传输,实现网络推流

一、瑞芯微RV1103介绍 RV1106及RV1103具有以下六大核心技术优势: 1、内置自研第4代NPU,最高达0.5TOPs算力 RV1106及RV1103采用Cortex-A7 CPU及高性能MCU,内置瑞芯微自研第4代NPU,运算精度高,支持int4、in8、int16混合…

WebGL开发的应用程序类型

WebGL是一种用于在Web浏览器中进行高性能图形渲染的JavaScript API,它主要用于创建交互式的3D图形和图像。通过WebGL,您可以开发多种类型的Web应用程序,包括但不限于以下几种,希望对大家有所帮助。北京木奇移动技术有限公司&#…

【前端】vscode 相关插件

一 插件: 01、ESLint 用来识别并检查ECMAScript/JavaScript 代码的工具 02、Prettier 用来格式化代码,如.js、.vue、css等都可以进行格式化 03、Vetur 用来识别并高亮vue语法 04、EditorConfig 用来设置vscode的编程行为 二、安装依赖 01、…

新年跨年烟花超酷炫合集【内含十八个烟花酷炫效果源码】

❤️以下展示为全部烟花特效效果 ❤️下方仅展示部分代码 ❤️源码获取见文末 🎀HTML5烟花喷泉 <style> * {padding:0;margin:0; } html,body {positi

TSX-3225 (MHz范围晶体单元微型低轮廓贴片)

TSX-322系列晶体谐振器是爱普生主推的一款无源晶振型号&#xff0c;频率范围16mhz ~ 48mhz&#xff0c;3.2*2.5mm较小的外部尺寸&#xff0c;可以广泛使用在手机&#xff0c;蓝牙&#xff0c;无线-局域网、ISM 频段电台广播&#xff0c;MPU时钟等产品中。 规范 运动阻力(ESR) 外…

基于ssm餐饮掌上设备点餐系统论文

餐饮掌上设备点餐系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了餐饮掌上设备点餐系统的开发全过程。通过分析餐饮掌上设备点餐系统管理的不足&#xff0c;创建了一个计算机管理餐饮掌上设备点餐系统的…

Enum in C,C++

C(C11以上&#xff09;&#xff1a; 第一种方式&#xff1a; /*** file duLangMap.h* author geovindu,Geovin Du(geovindu163.com)* brief vscode c11* version 0.1* date 2023-12-18** copyright Copyright (c) 站在巨人的肩膀上 Standing on the Shoulders of Giants 2023…

RK3568 android11 调试mipi摄像头 gc2093

一&#xff0c;摄像头简介 GC2093是一个高质量的1080P CMOS图像传感器&#xff0c;用于安全相机产品、数码相机产品和手机相机应用程序。包含了一个1920H x 1080V像素阵列、片上10位ADC和图像信号处理器。高性能和低功耗功能的全面集成使GC2093最适合设计&#xff0c;减少了实…