【数据结构】轻松掌握二叉树的基本操作及查找技巧

news2024/12/21 17:53:28

在这里插入图片描述

二叉树的基本操作

​ 在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在大家对二 叉树结构掌握还不够深入,为了降低学习成本,此处手动快速创建一棵简单的二叉树,快速进入二叉树操作学习,等二叉树结构了解的差不多时,再来研究二叉树真正的创建方式,下面用左右孩子法来定义二叉树结构体。

二叉树的结构体及创建:

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

void BinaryTreeCreate()
{
    BTNode* Node1 = BuyNode(1);
	BTNode* Node2 = BuyNode(2);
	BTNode* Node3 = BuyNode(3);
	BTNode* Node4 = BuyNode(4);
	BTNode* Node5 = BuyNode(5);
	BTNode* Node6 = BuyNode(6);
	BTNode* Node7 = BuyNode(7);
	Node1->left = Node2;
	Node2->left = Node4;
	Node1->right = Node3;
	Node2->right = Node5;
	Node3->right = Node6;
	Node3->left = Node7;
}

创建完二叉树的结构长这样

在这里插入图片描述

二叉树四大遍历

二叉树的遍历(traversing binary tree)是指从根结点出发按照某种次序依次访问二叉树中的所有结点,使得每个结点被访问一次目仅被访问一次

二叉树的遍历方式有很多,我们来介绍常见的四种:

  1. 前序遍历:先访问根节点,再访问左子树,最后访问右子树。

  2. 中序遍历:先访问左子树,再访问根节点,最后访问右子树。

  3. 后序遍历:先访问左子树,再访问右子树,最后访问根节点。

  4. 层序遍历:按照从上到下,从左到右遍历二叉树

按照上面创建的二叉树,N代表空,如果是前序的话124NN5NN37NN6NN,中序就是,NN4NN52NN7NN631,后序就是N4N2N5N1N7N3N6N,层序就是1234576

二叉树的前序遍历:

  • 如果二叉树为空,则返回空列表;
  • 如果二叉树不为空,则先访问根节点,再前序遍历左子树,最后前序遍历右子树。
void BinaryTreePrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N");
		return;
	}
	printf("%c", root->data);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);
}

二叉树的中序遍历:

  • 如果二叉树为空,则返回空列表;
  • 如果二叉树不为空,则先中序遍历左子树,再访问根节点,最后中序遍历右子树。
void BinaryTreeInOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N");
		return;
	}
	BinaryTreeInOrder(root->left);
	printf("%d", root->data);
	BinaryTreeInOrder(root->right);
}

二叉树的后序遍历:

  • 如果二叉树为空,则返回空列表;
  • 如果二叉树不为空,则先后序遍历左子树,再后序遍历右子树,最后访问根节点。
void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N");
		return;
	}
	BinaryTreePostOrder(root->left);
	BinaryTreePostOrder(root->right);
	printf("%d", root->data);
}

二叉树的层序遍历:

层序遍历是这四种遍历中最难实现的一种,我们需要借助队列的先进先出特性来实现层序遍历,先讲根节点入队,随后抛出并输出,抛出的同时将根结点的左右孩子拿进队,以此类推,由于队列是先进先出,所以每次输出都是按照拿左右孩子的顺序按照从上到下从左到右进行输出。

  • 如果二叉树为空,则返回空列表;
  • 如果二叉树不为空,则先将根节点入队列,然后循环执行以下操作:
    • 弹出队列头部节点,将其值加入结果列表;
    • 如果该节点有左子节点,则将左子节点入队列;
    • 如果该节点有右子节点,则将右子节点入队列。
void BinaryTreeLevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q,root);
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		printf("%d", front->data);
		QueuePop(&q);
		if (front->left)
			QueuePush(&q,front->left);
		if (front->right)
			QueuePush(&q,front->right);
	}
}

二叉树的结点及高度

二叉树节点个数

  • 如果二叉树为空,则结点个数为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);
}

二叉树叶子节点个数

  • 如果二叉树为空,则叶子节点个数为0;
  • 如果二叉树不为空:
    • 如果当前节点是叶子节点,则叶子节点个数为1;
    • 如果当前节点不是叶子节点,则叶子节点个数为左子树的叶子节点个数加上右子树的叶子节点个数。
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);
}

二叉树第k层节点个数

  • 如果二叉树为空,则第k层节点个数为0;
  • 如果k为1,则第k层节点个数为1;
  • 如果k大于1,则第k层节点个数为左子树的第k-1层节点个数加上右子树的第k-1层节点个数。
int BinaryTreeLevelSize(BTNode* root,int k)
{
	assert(k > 0);
	if (root == NULL)
		return 0;
	if (k == 1)
		return 1;
	return BinaryTreeLevelSize(root->left,k-1)+ BinaryTreeLevelSize(root->right,k-1);
}

二叉树查找值为x的节点

  • 如果二叉树为空,则返回空;
  • 如果当前节点的值等于x,则返回当前节点;
  • 否则,在左子树中递归查找值为x的节点,如果找到了,则返回找到的节点;否则,在右子树中递归查找值为x的节点,如果找到了,则返回找到的节点。
BTNode* BinaryTreeFind(BTNode* root,BTDataType x)
{
	if (root == NULL)
		return NULL;
	if (root->data == x)
		return root;
	BTNode* BinaryTreeLeft = BinaryTreeFind(root->left,x);
	if (BinaryTreeLeft)
		return BinaryTreeLeft;
	BTNode* BinaryTreeRight = BinaryTreeFind(root->right,x);
	if (BinaryTreeRight)
		return BinaryTreeRight;
	return NULL;
}

✨本文收录于数据结构理解与实现

当你喜欢一篇文章时,点赞、收藏和关注是最好的支持方式。如果你喜欢我的文章,请不要吝啬你的支持,点赞👍、收藏⭐和关注都是对我最好的鼓励。感谢你们的支持!

51.gif#pic_center)

✨本文收录于数据结构理解与实现

当你喜欢一篇文章时,点赞、收藏和关注是最好的支持方式。如果你喜欢我的文章,请不要吝啬你的支持,点赞👍、收藏⭐和关注都是对我最好的鼓励。感谢你们的支持!

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

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

相关文章

【自然语言处理】不同策略的主题建模方法比较

不同策略的主题建模方法比较 本文将介绍利用 LSA、pLSA、LDA、NMF、BERTopic、Top2Vec 这六种策略进行主题建模之间的比较。 1.简介 在自然语言处理(NLP)中,主题建模一词包含了一系列的统计和深度学习技术,用于寻找文档集中的隐…

【刷题之路】LeetCode 2073. 买票需要的时间

【刷题之路】LeetCode 2073. 买票需要的时间 一、题目描述二、解题1、方法1——记录每个人需要的时间1.1、思路分析1.2、代码实现 2、方法2——队列记录下标2.1、思路分析2.2、先将队列实现一下2.3、代码实现 一、题目描述 原题连接: 2073. 买票需要的时间 题目描述…

Linux---用户组命令(groupadd、groupdel、groupmod、newgrp、getent)

1. groupadd命令 [rootlocalhost ~]# groupadd [选项] 组名 [rootlocalhost ~]# groupadd group1 --向系统中增加了一个新组group1,新组的组标识号是在当前已有的最大组标识号的基础上加1。 [rootlocalhost ~]# groupadd -g 101 group2 --向系统中增加了一个新组gr…

MySQL5.7递归查询与CTE递归查询

文章目录 一、8.0版本的递归1、CTE递归2、举例3、递归CTE的限制 二、5.7版本的递归1、find_in_set 函数2、concat函数3、自定义函数实现递归查询4、向上递归5、可能遇到的问题 一、8.0版本的递归 1、CTE递归 先看8.0版本的递归查询CET。语法规则: WITH RECURSIVE…

深入浅出解析Stable Diffusion完整核心基础知识 | 【算法兵器谱】

Rocky Ding 公众号:WeThinkIn 写在前面 【算法兵器谱】栏目专注分享AI行业中的前沿/经典/必备的模型&论文,并对具备划时代意义的模型&论文进行全方位系统的解析,比如Rocky之前出品的爆款文章Make YOLO Great Again系列。也欢迎大家提…

笔试强训错题总结(一)

笔试强训错题总结 文章目录 笔试强训错题总结选择题编程题连续最大和不要二最近公共祖先最大连续的bit数幸运的袋子手套 选择题 以下程序的运行结果是&#xff08;&#xff09; #include <stdio.h> int main(void) {printf("%s , %5.3s\n", "computer&q…

<Linux开发>驱动开发 -之-基于pinctrl/gpio子系统的beep驱动

&#xff1c;Linux开发&#xff1e;驱动开发 -之-基于pinctrl/gpio子系统的beep驱动 交叉编译环境搭建&#xff1a; &#xff1c;Linux开发&#xff1e; linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下&#xff1a; &#xff1c;Linux开发&#xff1e; -之-系统移植…

如何在华为OD机试中获得满分?Java实现【人民币转换】一文详解!

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

认识Servlet---1

hi ,大家好,今天为大家带来Servlet相关的知识,并且实现第一个程序 &#x1f389;1.什么是Servlet &#x1f389;2.使用Servlet写一个hello程序 &#x1f33b;&#x1f33b;&#x1f33b;1.创建项目 &#x1f33b;&#x1f33b;&#x1f33b;2.引入依赖 &#x1f33b;&…

GitHub基本概念

创建日期: 2018-09-22 09:50:06 Git & GitHub Git是一个版本控制软件&#xff1a; 读作[gɪt] ,拼音读作gē y te。 Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed an…

STM32之温湿度LCD显示并上传服务器

目录 项目需求 项目框图 硬件清单 LCD1602介绍及实战 硬件接线 引脚封装 代码实现 DHT11介绍及实战 硬件接线 引脚封装 代码实现 项目设计及实现 项目设计 项目实现 项目需求 使用温湿度传感器模块&#xff08; DHT11 &#xff09;获取温度及湿度&#xff0c…

推荐计算机领域的几本入门书籍

人工智能入门&#xff1a; 人工智能&#xff1a;现代方法&#xff08;第4版&#xff09;揭示AI与chatgpt的奥秘&#xff0c;详解人工智能的发展与未来&#xff01; 推荐理由&#xff1a;系统性总结人工智能的方方面面&#xff0c;国际人工智能领域专家斯图尔特罗素撰写人工智能…

YOLO-NAS对象检测算法再一次颠覆YOLO系列算法——已超越YOLOv8

对象检测彻底改变了机器感知和解释人类世界的方式。这是计算机视觉中一项特别关键的任务,使机器能够识别和定位图像或视频中的物体。如自动驾驶汽车、面部识别系统等。推动对象检测进步的一个关键因素是发明了神经网络架构。强大的神经网络推动了对象检测的进步,增强了计算机…

Meta Learning

Meta Learning&#xff08;元学习&#xff09;是一种机器学习技术&#xff0c;它的核心思想是学习如何学习。 Meta Learning的目标是从以前的学习经验中学习到通用的学习策略和模式&#xff0c;以便在新的任务上快速适应和学习。 Meta Learning的核心思想是将学习任务视为元任…

Vivado下阻塞赋值和非阻塞赋值的对比

Verilog 基础知识 中已经介绍过了阻塞赋值和非阻塞赋值的区别&#xff0c;下面通过一个在Vivado中的简单例子来直观的反映两者的不同。 首先给出设计源代码如下。 module block(a,b,c,clk,x);input x;input clk;output reg a,b,c;always(posedge clk) begina x; //阻塞赋值…

零钱兑换,凑零钱问题,从暴力递归到动态规划(java)

凑零钱问题&#xff0c;从暴力递归到动态规划 leetcode 322 题 零钱兑换暴力递归&#xff08;这个会超时&#xff0c;leetcode 跑不过去&#xff09;递归缓存 leetcode 322 题 零钱兑换 322 零钱兑换 - 可以打开链接测试 给你一个整数数组 coins &#xff0c;表示不同面额的硬…

[MAUI]模仿Chrome下拉标签页的交互实现

文章目录 创建粘滞效果的圆控件贝塞尔曲线绘制圆创建控件创建形变可控形变形变边界形变动画 创建手势控件创建页面布局更新拖拽物位置其它细节 项目地址 今天来说说怎样在 .NET MAUI 中制作一个灵动的类标签页控件&#xff0c;这类控件常用于页面中多个子页面的导航功能。 比如…

《数据库应用系统实践》------ 公园游客日流量管理系统

系列文章 《数据库应用系统实践》------ 公园游客日流量管理系统 文章目录 系列文章一、需求分析1、系统背景2、 系统功能结构&#xff08;需包含功能结构框图和模块说明&#xff09;3&#xff0e;系统功能简介 二、概念模型设计1&#xff0e;基本要素&#xff08;符号介绍说明…

【阅读笔记】概率预测之MQ-RNN(含Pytorch代码实现)

本文作为自己阅读论文后的总结和思考&#xff0c;不涉及论文翻译和模型解读&#xff0c;适合大家阅读完论文后交流想法&#xff0c;关于论文翻译可以查看参考文献。论文地址&#xff1a;https://arxiv.org/abs/1711.11053 MQ-RNN 一. 全文总结二. 研究方法三. 结论四. 创新点五…

谷歌推出免费AI编程神器Colab,欲将Copilot拉下神坛

在如今的AI编码工具领域&#xff0c;微软旗下的Github Copilot可以算得上是一家独大&#xff0c;而作为老对手的谷歌显然并不愿屈服于此。 近日&#xff0c;谷歌通过其官网高调发文宣布&#xff0c;将为研发工具Google Colaboratory&#xff08;Colab&#xff09;加入全新的AI…