【数据结构与算法】一文拿捏链式二叉树:遍历 + 统计 + 层序 + 完全树

🔥小龙报:个人主页

🎬作者简介:C++研发,嵌入式,机器人等方向学习者

❄️个人专栏:《C语言》《数据结构与算法》
永远相信美好的事情即将发生



文章目录


前言

二叉树是数据结构中的核心内容,链式存储是其最常用的实现方式。本文围绕链式二叉树展开,从结构创建入手,详细讲解前中后序遍历、节点个数统计、叶子节点计算、层序遍历及完全二叉树判断等核心操作,结合代码实现与运行效果,帮助初学者快速掌握二叉树的基本原理与实操技巧,夯实数据结构基础。


一、创建链式结构二叉树

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

html 复制代码
typedef struct BinaryNode
{
    BinaryDataType x;
    struct BTNode* left; //左孩子
    struct BTNode* right; //右孩子

}BTNode;

注:我们为了方便后续的使用,先手动创建一颗链式二叉树

html 复制代码
BTNode* CreatTree()
{
	BTNode* nodeA = buyNode('A');
	BTNode* nodeB = buyNode('B');
	BTNode* nodeC = buyNode('C');
	BTNode* nodeD = buyNode('D');
	BTNode* nodeE = buyNode('E');
	BTNode* nodeF = buyNode('F');

	nodeA->left = nodeB;
	nodeA->right = nodeC;
	nodeB->left = nodeD;
	nodeC->left = nodeE;
	nodeC->right = nodeF;

	return nodeA;
}

二、前中后序遍历

  1. 前序遍历(先根遍历) :先遍历根节点,再遍历左子树,最后遍历右子树----根左右
  2. 中序遍历 :先遍历左子树,再遍历根节点,最后遍历右子树----左根右
  3. 后续遍历 :先遍历左子树,再遍历右子树,最后遍历根节点----左右根

2.1 前序遍历

规则根左右

html 复制代码
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	//根左右
	printf("%c ", root->x);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);

}

运行结果

遍历顺序图

这里红线统一表示递归,另一个表示回退

函数递归栈栈图 :(标的序号表示打印的顺序)

2.2 中序遍历

规则:左根右

html 复制代码
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	//左根右
	BinaryTreeInOrder(root->left);
	printf("%c ", root->x);
	BinaryTreeInOrder(root->right);
}

运行结果

函数递归栈栈图:(标的序号表示打印的顺序)

2.3 后序遍历

规则:左右根

html 复制代码
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	//左右根
	BinaryTreePostOrder(root->left);
	BinaryTreePostOrder(root->right);
	printf("%c ", root->x);
}

运行结果

函数递归栈栈图 :(标的序号表示打印的顺序)

三、二叉树节点个数

二叉树结点个数=根节点+左子树结点个数+右子树结点个数

运行结果

四、二叉树叶子节点个数

二叉树的叶子节点就是左右孩子都为空的节点

公式 :
二叉树叶子节点个数=左子树叶子节点个数+右子树叶子节点个数

html 复制代码
// 二叉树叶子节点个数:左子树叶子节点个数+右子树节点个数
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层节点个数=左子树第k-1层节点个数+右子树第k-1层节点个数

html 复制代码
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	if (root == NULL)
		return 0;

	if (k == 1)
		return 1;
	return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}

运行结果

六、二叉树查找值为x的节点

递归查找,找到了就返回当前节点,如果是在左子树中找到就直接返回,没找到继续来到右子树找,最好都没找到就返回NULL

七、层序遍历

准备工作

1.我们需要先把队列的.c和.h文件导入到当前vs项目中,然后在Tree.c文件里面包含上Queue.h文件


前置声明

html 复制代码
//二叉树的层序遍历
void LevelOrder(BTNode* root)
{
	Queue q;
    QueueInit(&q); //初始化队列
    QueuePush(&q, root); //根节点入队
	while (!QueueIsEmpty(&q))
	{
       BTNode* front = QueueFront(&q);
       printf("%c ", front->x);
       QueuePop(&q);
       if (front->left) //左子树入队
           QueuePush(&q, front->left);
       if (front->right) //右子树入队
           QueuePush(&q, front->right);
	}

	QueueDestroy(&q); //销毁队列
}

运行结果

图解

八、判断是否为完全二叉树

html 复制代码
//判断是否为完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	//根节点入队
	QueuePush(&q, root);

	//遍历
	while (!QueueIsEmpty(&q))
	{
		//取队首,然后出队首
		BTNode* top = QueueFront(&q);
		QueuePop(&q);
		if (top == NULL)
		{
			//top取到空直接出队列
			break;
		}
		//将top的左右孩子节点全部入队
		QueuePush(&q, top->left);
		QueuePush(&q, top->right);
	}

	//队列不为空,继续取队列中的队头
	while (!QueueIsEmpty(&q))
	{
		BTNode* top = QueueFront(&q);
		if (top != NULL)
		{
			//有不是NULL的就不是完全二叉树
			QueueDestroy(&q);
			return false;
		}
		QueuePop(&q);
	}
	QueueDestroy(&q);
	return true;
}

总结与每日励志

本文完整覆盖链式二叉树的创建、遍历、各类节点统计及完全二叉树判断等关键知识点,核心是递归思想与队列工具的灵活运用。学习二叉树需多练多思考,正视每一个报错与疑问。愿你在数据结构的学习路上,不慌不忙、循序渐进,把每一个知识点吃透,把每一行代码写扎实。永远相信美好的事情即将发生,坚持下去,终会收获成长与突破!

相关推荐
蔡俊锋2 小时前
AI代理落地指南:从Demo到生产级的实战攻略
人工智能·深度学习·hermes·ai团队知识沉淀
最后一只小白2 小时前
聊天状态以及流畅运行
人工智能·语音识别
mahtengdbb12 小时前
SimAM无参数注意力机制改进YOLOv26神经科学启发的自适应特征增强突破
人工智能·yolo·目标跟踪
喵叔哟2 小时前
10.【.NET10 实战--孢子记账--产品智能化】--其余第三方包批量升级
人工智能·.net
TE-茶叶蛋2 小时前
Spring 高级机制:循环依赖 + AOP + @Transactional 失效原理
java·后端·spring
做cv的小昊2 小时前
【TJU】研究生应用统计学课程笔记(5)——第二章 参数估计(2.3 C-R不等式)
c语言·笔记·线性代数·机器学习·数学建模·r语言·概率论
MF_AI2 小时前
YOLO无人机视角检测识别数据集汇总
人工智能·深度学习·yolo·目标检测·视觉检测·无人机
重庆若鱼文化创意2 小时前
高端包装设计公司哪家好,报价差异常藏在纸张和印刷工艺里。
人工智能·python
juniperhan2 小时前
Flink 系列第18篇:Flink 动态表、连续查询与 Changelog 机制
java·大数据·数据仓库·分布式·flink