二叉树入门

这篇博客通过手动创建的一个简单二叉树,实现二叉树遍历,返回节点,叶子个数,查找结点等相关操作。

1. 二叉树的概念
二叉树不为空时,由根节点,左/右子树组成,逻辑结构如下,当二叉树为空时称为空树。
我们可以看到,左子树同样可以看作是根节点和左右子树构成,因此二叉树的基本操作需要利用递归的方式得以实现。此处需要注意的是,每次递归返回值不一定是传递给最外层的。
2.二叉树的遍历 
二叉树的遍历按照规则分为三种情况,分别是前序遍历中序遍历以及后序遍历。前序遍历先访问根节点再访问左右子树,中序遍历先访问左子树,再访问根节点和右子树,后序遍历先访问左右子树最后访问根节点。因此根据上述二叉树的排列不难写出二叉树的三种遍历情况,我们将NULL简写成 N,如下图所示:

在代码实现的过程中,我们先创建节点,在更改节点的指向,即可实现我们需要的上述的结构:
typedef int BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

BTNode* BuyNode(BTDataType x)
{
	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	
	newnode->left = NULL;//初始化
	newnode->right = NULL;
	newnode->data = x;
	return newnode;
}

BTNode* creatBinaryTree()
{
	BTNode* node1 = BuyNode(1);
	BTNode* node2 = BuyNode(2);
	BTNode* node3 = BuyNode(3);
	BTNode* node4 = BuyNode(4);
	BTNode* node5 = BuyNode(5);
	BTNode* node6 = BuyNode(6);

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

实现三种情况的遍历,我们可以通过递归实现,因为二插树可以分成根节点和左右子树,左右子树又可以分为根节点和下一个左右子树,直到叶节点。代码如下:
void preorder(BTNode* root) //前序遍历
{
	if (root == NULL) 
	{
		printf("N ");
		return;
	}
	printf("%d ",root->data);
	preorder(root->left);
	preorder(root->right);
}
void Inorder(BTNode* root)//中序遍历
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	
	Inorder(root->left);
	printf("%d ", root->data);
	Inorder(root->right);
}
void postorder(BTNode* root)//后续遍历
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	postorder(root->left);
	postorder(root->right);
	printf("%d ", root->data);
}
3.二叉树结点的个数
求二叉树结点的个数,也是同样的道理,计算左右子树结点之和+1即可。 
int BTreeSize(BTNode* root)//分治求节点的个数
{
	if (root == NULL)
	{
		return 0;
	}
	return BTreeSize(root->left)
		+ BTreeSize(root->right) + 1;
}
4.求叶子节点的个数
叶子节点的左右子树均为空,按照这个结束条件设计递归即可。
int BTreeLeafSize(BTNode* root)//求叶子节点的个数
{
	if (root == NULL)
	{
		return 0;
	}

	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}
	
	return BTreeLeafSize(root->left) + BTreeLeafSize(root->right) ;
}
 5. 二叉树的最长路径
将求最长路径问题分成求左右子树的最长路径,之后取大的值即可。
int BTreeHeight(BTNode* root)//最长的路径
{
	if (root == NULL)//一定要判空树
	{
		return 0;
	}
	int leftHeight = BTreeHeight(root->left);
	int rightHeight = BTreeHeight(root->right);

	return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;	
}
6. k层二叉树的节点个数 
 k层二叉树的节点个数问题可转化成左右节点k-1层节点个数之和,递归的结束条件是k == 1且节点不为空,以及节点为空。
int BTreeLevelKsize(BTNode* root,int k)//子问题,结束条件
{
	assert(k>0);
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}

	return BTreeLevelKsize(root->left, k - 1) 
		+ BTreeLevelKsize(root->right, k - 1);

}
 7. 查找值并返回节点的地址
依然是递归调用,分为左右节点。
BTreeFind(BTNode* root, BTDataType x) 
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->data == x)
	{
		return root;
	}
	BTNode* ret1 = BTreeFind(root->left, x);	
	if (ret1)
	{
		return ret1;
	}
	BTNode* ret2 = BTreeFind(root->right, x);	
	if (ret2)
	{
		return ret2;
	}
	return NULL;
}
8. 结果
int main()
{
	BTNode* root =creatBinaryTree();
	preorder(root);
	printf("\n");
	Inorder(root);
	printf("\n");
	postorder(root);
	printf("\n");
	printf("BTreeSize = %d\n", BTreeSize(root));
	printf("BTreeLeafSize = %d\n", BTreeLeafSize(root));
	printf("BTreeHeight = %d\n", BTreeHeight(root));
	printf("BTreeLevelKsize = %d\n", BTreeLevelKsize(root,3));
	printf("BTreeLevelKsize = %d\n", BTreeLevelKsize(root, 2));
	
	return 0;
}


 

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

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

相关文章

上班族真香副业:工资4500,靠steam游戏搬砖项目月入过w

steam游戏搬砖项目已经存在好多年了,这个项目比较冷门且能持续稳定盈利,是一个非常不错的项目。即使你没玩过steam游戏也没关系,这个steam游戏搬砖项目既不需要你会玩游戏,也不需要你懂英语。 steam游戏搬砖项目的盈利点在汇率差和…

Lwip之TCP服务端示例记录(1对多)

前言 实现多个客户端同时连接初步代码结构已经实现完成(通过轮训的方式) // // Created by shchl on 2024/3/8. // #if 1#include <string.h> #include "lwip/api.h" #include "FreeRTOS.h" #include "task.h" #include "usart.h&…

寻找数组的中心索引

给你一个整数数组 nums &#xff0c;请计算数组的 中心下标 。 数组 中心下标 是数组的一个下标&#xff0c;其左侧所有元素相加的和等于右侧所有元素相加的和。 如果中心下标位于数组最左端&#xff0c;那么左侧数之和视为 0 &#xff0c;因为在下标的左侧不存在元素。这一点…

斐讯N1 刷coreelec 笔记

1.下载恩山的镜像 下载好后不需要刷优盘 这个很方便&#xff0c;可以勾选擦除flash &#xff08;如果第一次装&#xff09; 升级可以不用勾选 详细使用参考恩山大佬的描述 2.下载插件 想装openwrt 发现镜像里面 coreelec-addons 挂了&#xff0c;研究了好长时间可以 去githu…

一文扫荡,12个可视化图表js库,收藏备用。

hello&#xff0c;我是贝格前端工场&#xff0c;可视化图表在web前端开发中经常碰到&#xff0c;是不是很疑惑这些炫酷的图表是怎么实现的&#xff0c;其实是通过js库开发的&#xff0c;本文带来12个javascript库的介绍&#xff0c;欢迎关注我&#xff0c;阅读精彩内容。 一、什…

2024 RubyMine 激活,分享几个RubyMine 激活的方案

文章目录 RubyMine 公司简介我这边使用RubyMine 的理由RubyMine 2023.3 最新变化AI Assistant 正式版对 AI 生成名称建议的支持改进了 Ruby 上下文单元测试生成 RailsRails 应用程序和引擎的自定义路径Rails 路径的自动导入对存储在默认位置之外的模型、控制器和邮件器的代码洞…

Express学习(三)

Express中间件 中间件的概念 什么是中间件 中间件&#xff0c;特指业务流程的中间处理环节。Express中间件的调用流程 当一个请求到达Express的服务器之后&#xff0c;可以连续调用多个中间件&#xff0c;从而对这次请求进行预处理。类似于下图所示 Express中间件的格式 Expr…

C++进阶之路---继承(二)

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、继承与友元 友元关系不能继承&#xff0c;也就是说基类友元不能访问子类私有和保护成员。 class Student; class Per…

[C语言]——分支和循环(4)

目录 一.随机数生成 1.rand 2.srand 3.time 4.设置随机数的范围 猜数字游戏实现 写⼀个猜数字游戏 游戏要求&#xff1a; &#xff08;1&#xff09;电脑自动生成1~100的随机数 &#xff08;2&#xff09;玩家猜数字&#xff0c;猜数字的过程中&#xff0c;根据猜测数据的⼤…

【LaTeX】行内代码块、行间代码块的插入以及高亮(懒人版)

文章目录 思路和优点基本框架行内代码行间代码pythoncpp 所支持的语言所支持的代码风格 思路和优点 思路是listingsminted包&#xff0c; 一个负责插入代码一个负责高亮代码 这种方法显著的优点在于&#xff1a;完全不需要自定义代码风格 使用其他方法时&#xff0c;你定义好…

嵌入式学习36-TCP要点及http协议

TCP发送文件的粘包问题 1. 例&#xff1a; 发端 1.flv-------->收端 1.flv csfga 2.解决 1. sleep&#xff08;1&#xff09; 延时发送 2.自…

httprunner用例结构(前后置)

说明&#xff1a;httprunner 结合 pytest 的前后置方式 1. 用例级别前后置 1.1. setup teardown class TestCaseRefTestcase(HttpRunner):# 用例级别前后置def setup(self):logger.warning("------用例级别前置")def teardown(self):logger.warning("------用…

用一个 Python 脚本实现依次运行其他多个带 argparse 命令行参数的 .py 文件

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 问题描述&#xff1a;在 Windows 环境中&#xff0c;您希望通过一个 Python 脚本来实现特定的自动化任务&#xff0c;该任务需要依次运行其他多个带 argparse 命令行参数的 .py 文件。您希望找到一种简…

【jenkins】简单安装及配置(Windows环境)

前言 jenkins是一款跨平台的持续集成和持续交付、基于Java开发的开源软件&#xff0c;提供任务构建、持续集成监控的功能&#xff0c;可以使开发测试人员更方便的构建软件项目&#xff0c; 提高工作效率。Windows平台下&#xff0c;一般安装方法有2种&#xff1a;安装程序安装…

unicloud where 使用

where介绍 在uniCloud中&#xff0c;WHERE是一个用于指定查询条件的关键字。它允许用户根据特定的条件来筛选和查询云数据库中的数据。WHERE语句的基本语法格式是WHERE condition&#xff0c;其中condition表示查询条件&#xff0c;可以是一个或多个逻辑表达式组成的条件。 在…

第七十九天 WAF攻防-漏洞发现协议代理池GobyAWVSXray

第79天 WAF攻防-漏洞发现&协议&代理池&Goby&AWVS&Xray 知识点&#xff1a; 1、Http/s&Sock5协议 2、Awvs Xray&Goby代理 3、Pxoxifier进程代理使用 4、Safedog&BT&Aliyun防护 演示案例&#xff1a; Awws漏扫-Sadedog-白名单-内置 Awws漏…

使用Apache Kafka的Golang实践指南

您是否在寻找构建可扩展、高性能应用程序的方法&#xff0c;这些应用程序可以实时处理流数据&#xff1f;如果是的话&#xff0c;结合使用Apache Kafka和Golang是一个很好的选择。Golang的轻量级线程非常适合编写类似Kafka生产者和消费者的并发网络应用程序。它的内置并发原语&…

动态规划DP之背包问题3---多重背包问题

目录 DP分析&#xff1a; 优化&#xff1a; 二进制优化 例题&#xff1a; 01背包是每个物品只有一个&#xff0c;完全背包问题是每个物品有无限个。 那么多重背包问题就是 每个物品有有限个。 有 N 种物品和一个容量是 V 的背包。 第 i 种物品最多有 si 件&#xff0c;每件体…

Mysql学习笔记之事务详解(读未提交、读以提交、可重复读、串行化读)

在这个博主的基础上&#xff0c;增加两种情况的对比&#xff1a;https://blog.csdn.net/llllllkkkkkooooo/article/details/108068919 可重复读中幻读现象&#xff08;未使用MVCC&#xff09; 设置可重复读的隔离级别 set global transaction isolation level repeatable read…

代码随想录算法训练营第day40|343. 整数拆分 、 96.不同的二叉搜索树

a.343. 整数拆分 题目链接 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1 1 1。 示例 2: 输入: …