二叉树的四种遍历详解(先序,中序,后序,层次)

news2025/1/10 12:12:58

目录

引言:

1:先序遍历

2.中序遍历

3.后续遍历

4.层次遍历

先序中序后序例题:

例题1:

例题2:

层次遍历例题:

结语:


引言:

二叉树的遍历的概念:二叉树遍历是指按照一定的次序访问二叉树中的所有结点,并且每个结点仅被访问一次的过程。它是二叉树最基本的运算,是二叉树中所有其它运算实现的基础。

为了帮助大家理解各类的遍历过程,下面我给出一个二叉树,下面的各类遍历结果都是根据这张图的图片如下:

二叉树的遍历各类过程:

先序中序和后序都是利用递归来实现的。

层次遍历使用队列实现的

1:先序遍历

(1)访问跟结点

(2)先序遍历左子树

(3)先序遍历右子树

图所示的二叉树的先序序列位ABDGCEF。

先序的代码:

先访问根节点再访问左子树后右子树。

//先序遍历
void PreOrder(BTNode* b)
{
	if (b != NULL)
	{
		printf("%c ", b->data);
		PreOrder(b->lchild);
		PreOrder(b->rchild);
	}
	return;
}

2.中序遍历

(1)中序遍历左子树

(2)访问跟结点

(3)中序遍历右子树

图所示的二叉树的中序序列位DGBAECF。

中序的代码:

先访问左子树,再访问根结点,最后是右子树。

//中序遍历
void InOrder(BTNode* b)
{
	if (b != NULL)
	{
		InOrder(b->lchild);
		printf("%c ", b->data);
		InOrder(b->rchild);
	}
	return;
}

3.后续遍历

(1)后序遍历左子树

(2)后序遍历右子树

(3)访问根结点

图所示的二叉树的中序序列位GDBEFCA。

后序的代码:

先访问左子树再访问右子树,最后是根结点。

//后序遍历
void PostOrder(BTNode* b)
{
	if (b != NULL)
	{
		PostOrder(b->lchild);
		PostOrder(b->rchild);
		printf("%c ", b->data);
	}
	return;
}

4.层次遍历

(1)访问根节点(第一层)

(2)从左到右访问第二层的所有结点。

(3)从左到右访问第三层的所有结点.....第h层的所有结点。

图所示的二叉树的中序序列位ABCDEFG。

层次的代码:

层次是用队列来实现的下面这个代码只是思路,完整代码后续给出。

那么为什么后想到用队列来实现呢?我们可以观察到,二叉树的层次遍历就是按层次从上到下,每一层从左到右的顺序访问树中的全部结点。故某一层中先访问的结点在下一层中它的孩子也先访问,这样不就和我们的队列特性相符合吗,因此层次遍历算法采用一个队列qu来实现。算法中的队列采用顺序队存储结构。

队列的图片如下:

//层次遍历
typedef struct Node
{
	BTNode* data[MaxSize];
	int front, rear;
}SqQueue;
void LevelOrder(BTNode* b)
{
	BTNode* p=NULL;
	SqQueue* qu;
	qu = InitQueue();
	enQueue(qu, b);
	while (!EmptyQueue(qu))
	{
		deQueue(qu, &p);
		printf("%c ", p->data);
		if (p->lchild != NULL)
			enQueue(qu, p->lchild);
		if (p->rchild != NULL)
			enQueue(qu, p->rchild);
	}
	DestroyQueue(qu);
}

以上便是各类遍历的基本思路,下面我会结合一下运用遍历的例题来帮助大家理解,因为文章篇幅有限,故例题只给出实现函数部分,没有给出主函数,特别说明最后面我会给出一个主函数(非常完整),大家例题中的代码都能带进去运行,方便大家调试理解由于层次遍历和前面三种遍历实现方法不太一样,故下面的例题会分为,前面三种遍历和层次遍历。

先序中序后序例题:

例题1:

设计一个算法,输出一颗给定二叉树的所有结点。

即输出:GEF结点

对应的函数如下DispLeaf(BTNode*b)

通过判断有无孩子结点来判断他是不是叶子结点(最下面那个结点),如果不是就递归左右子树找叶子。此题三种遍历都能实现,下面代码是先序遍历,如果把if和DispLeaf(b->lchild);交换就变成中序遍历,同理如果把DispLeaf(b->lchild)和 DispLeaf(b->rchild);同时先上移,这样就变成后序遍历。

void DispLeaf(BTNode* b)//求叶子结点
{
	if (b != NULL)
	{
		if (b->lchild == NULL && b->rchild == NULL)
		{
			printf("%c ", b->data);
		}
		DispLeaf(b->lchild);
		DispLeaf(b->rchild);
	}

}

运行结果如下:

例题2:

设计一个算法求二叉树b中第k层的结点个数。

思路如下:函数名为void Lnodenum(BTNode* b, int h, int k, int* n),其中h表示b所指的结点层次,n是引用型参数,由于求第k层的结点个数,在初始调用时,b为根结点指针,h为1,n赋值为0,即调用方式时n=0;Lnodenum(b, 1, k, &t);

采用先序遍历的函数如下,如果想用中序和后序的话按照例题一的修改方法即可。

void Lnodenum(BTNode* b, int h, int k, int* n)
{
	if (b == NULL)
	{
		return;
	}
	else if (h == k)
	{
		if(b->data!=' ') *n = *n + 1;		
		return;
	}
	else if (h < k)
	{
		Lnodenum(b->lchild, h + 1, k, n);//特别注意不要&n
		Lnodenum(b->rchild, h + 1, k, n);
	}
}

运行结果如下:

对照上面给出的二叉树的图大家可以试试。

对应的main函数。

直接将上面的两个函数加进去即可,其中CreateBTree和DispBTree在我的上一篇文章二叉树的基本运算中已经讲的很清楚了,如果有朋友们不是很清楚的话,可以去上一篇文章看看,写的很详细哦。

#define  _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
#define MaxSize 100
typedef struct node
{
	struct node* lchild, * rchild;
	ElemType data;
}BTNode;
BTNode* CreateBTree(char* str)
{
	BTNode* SqStack[MaxSize];
	BTNode* b;
	BTNode* p = NULL;
	b = NULL;
	int top = -1;
	char ch;
	int j = 0;
	ch = str[j];
	int k = 0;
	while (ch != '\0')
	{
		switch (ch)
		{
		case '(':k = 1; top++; SqStack[top] = p; break;
		case ')':top--; break;
		case ',':k = 2; break;
		default:
		{
			p = (BTNode*)malloc(sizeof(BTNode));
			p->data = ch;
			p->lchild = p->rchild = NULL;
			if (b == NULL)
			{
				b = p;
			}
			else
			{
				switch (k)
				{
				case 1:SqStack[top]->lchild = p; break;
				case 2:SqStack[top]->rchild = p; break;
				}
			}
		}
		}
		j++;
		ch = str[j];
	}
	return b;
}
void DispBTree(BTNode* b)
{
	if (b != NULL)
	{
		printf("%c", b->data);
		if (b->lchild != NULL || b->rchild != NULL)
		{
			printf("(");
			DispBTree(b->lchild);
			if (b->rchild != NULL) printf(",");
			DispBTree(b->rchild);
			printf(")");
		}
	}

}


int main()
{
	char str[] = "A(B(D( ,G)),C(E,F))";
	BTNode* b = CreateBTree(str);
	//DispLeaf(b);
	int t = 0;
	Lnodenum(b, 1, 3, &t);
	printf("%d", t);
	//DispBTree(b);
	return 0;
}

层次遍历例题:

设计一个算法将二叉树按层次遍历输出:

层次遍历过程是先将根结点进队,在队不空是循环:出队一个结点p并访问它,若它有左孩子,将左孩子进队:若它有右孩子,将有孩子进队。如此操作,直到队空为止。次过程称为基本层次遍历过程,对应的算法代码如下。本身代码不多主要是实现队列挺麻烦的(这就是为什么c语言没有别的语言效率那么高的原因,别的语言有的自带队列)。

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
typedef char ElemType;
#define MaxSize 100
typedef struct node
{
	struct node* lchild;
	struct node* rchild;
	ElemType data;
}BTNode;
typedef struct 
{
	BTNode* data[MaxSize];
	int front, rear;
}SqQueue;
//基本层次遍历算法
SqQueue* InitQueue()
{
	SqQueue* obj = (SqQueue*)malloc(sizeof(SqQueue));
	obj->front = obj->rear = -1;
	return obj;
}
bool enQueue(SqQueue* qu, BTNode* b)
{
	qu->rear++;
	qu->data[qu->rear] = b;
	return true;
}
bool EmptyQueue(SqQueue* qu)
{
	return (qu->front == qu->rear);
}
bool deQueue(SqQueue* qu, BTNode** b)
{
	qu->front++;
	*b = qu->data[qu->front];
	return true;
}
void DestroyQueue(SqQueue* qu)
{
	free(qu);
}
void LevelOrder(BTNode* b)
{
	BTNode* p = NULL;
	SqQueue* qu;
	qu = InitQueue();
	enQueue(qu, b);
	while (!EmptyQueue(qu))
	{
		deQueue(qu, &p);
		printf("%c ", p->data);
		if (p->lchild != NULL)
			enQueue(qu, p->lchild);
		if (p->rchild != NULL)
			enQueue(qu, p->rchild);
	}
	DestroyQueue(qu);
}
BTNode* CreateBTree(char str[])
{
	BTNode* b = (BTNode*)malloc(sizeof(BTNode));
	BTNode* St[MaxSize];
	b = NULL;
	BTNode* p = NULL;
	int top = -1;
	char ch;
	int j = 0;
	ch = str[j];
	int k;
	while (ch != '\0')
	{
		switch (ch)
		{
		case '(':top++; St[top] = p; k = 1; break;
		case ')':top--; break;
		case ',':k = 2; break;
		default:
		{
			p = (BTNode*)malloc(sizeof(BTNode));
			p->data = ch;
			p->lchild = p->rchild = NULL;
			if (b == NULL)
			{
				b = p;
			}
			else
			{
				switch (k)
				{
				case 1:St[top]->lchild = p; break;
				case 2:St[top]->rchild = p; break;
				}
			}
		}
		}
		j++;
		ch = str[j];
	}
	return b;
}
int main()
{
	char str[] = "A(B(D( ,G)),C(E,F))";
	BTNode* b = CreateBTree(str);
	LevelOrder(b);
}

以上便是先序中序后序层次遍历的算法及例题。文章到这也就到了尾声啦,感谢观看🎉🎉🎉

结语:

其实写博客不仅仅是为了教大家,同时这也有利于我巩固自己的知识点,和一个学习的总结,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进,如果大家有所收获的话还请不要吝啬你们的点赞收藏和关注,这可以激励我写出更加优秀的文章。

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

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

相关文章

GZ075 云计算应用赛题第10套

2023年全国职业院校技能大赛&#xff08;高职组&#xff09; “云计算应用”赛项赛卷10 某企业根据自身业务需求&#xff0c;实施数字化转型&#xff0c;规划和建设数字化平台&#xff0c;平台聚焦“DevOps开发运维一体化”和“数据驱动产品开发”&#xff0c;拟采用开源OpenS…

管理configration Manager 控制台

一、configration manager客户端安装 1.点击管理&#xff0c;扩展站点配置&#xff0c;点击站点 2.右键主站点&#xff0c;选择客户端安装设置 3.出现客户端请求安装属性对话框后&#xff0c;点击常规。点击启用自动站点范围客户端请求安装 4.点击账户 5.点击安装属性&#x…

Windows 10 Microsoft Edge浏览器无法打

早上到公司发现Microsoft Edge浏览器突然间打不开了&#xff0c;怎么点击快捷方式都不行&#xff0c;然后尝试了以下方法都不行&#xff1a; 1、右键使用“管理者身份运行”打开&#xff0c;无效。 2、账户注销&#xff0c;再次点击快捷方式。 3、重启电脑无效。 然后快捷方式右…

轻松制作商业画册的秘籍

对于许多商业人士来说&#xff0c;制作一本精美的商业画册是一个重要的任务&#xff0c;它不仅代表了公司的形象&#xff0c;也是与客户和潜在客户建立联系的重要工具。然而&#xff0c;制作一本商业画册并不像看起来那么简单。有许多因素需要考虑&#xff0c;包括设计、布局、…

当代大学生是怎么被废掉的?

中式教育以应试为核心&#xff0c;强调知识的灌输和学生被动接受。随着社会的发展&#xff0c;中式教育的短板逐渐显现&#xff0c;创新能力的缺乏、对记忆的过度依赖、忽视个体差异等问题日益突出。 建议所有大学生都能去看看《上海交通大学生存手册》&#xff0c;它道出了中…

前任开发在代码里下毒了,支付下单居然没加幂等

分享是最有效的学习方式。 故事 又是一个风和日丽没好的一天&#xff0c;小猫戴着耳机&#xff0c;安逸地听着音乐&#xff0c;撸着代码&#xff0c;这种没有会议的日子真的是巴适得板。 不料祸从天降&#xff0c;组长火急火燎地跑过来找到了小猫。“快排查一下&#xff0c;目…

C++内存管理机制(侯捷)笔记3

C内存管理机制&#xff08;侯捷&#xff09; 本文是学习笔记&#xff0c;仅供个人学习使用。如有侵权&#xff0c;请联系删除。 参考链接 Youtube: 侯捷-C内存管理机制 Github课程视频、PPT和源代码: https://github.com/ZachL1/Bilibili-plus 第三讲&#xff1a;malloc和…

如何手写一个RPC?

在学习 RPC 框架之前&#xff0c;我们先来手写一个RPC。 我们在学习的过程中&#xff0c;一定要做到知其然&#xff0c;还要知其所以然。 架构演进 单体架构 要知道&#xff0c;在以前单体架构的时候&#xff0c;会将所有的应用功能都集中在一个服务当中。 单体架构初始开发…

学习Java API(三):基础知识点一文通✅

推荐阅读 智能化校园&#xff1a;深入探讨云端管理系统设计与实现&#xff08;一&#xff09; 智能化校园&#xff1a;深入探讨云端管理系统设计与实现&#xff08;二&#xff09; 文章目录 推荐阅读Date 类SimpleDateFormatCalendar Date 类 java.util 包提供了 Date 类来封…

UI自动化测试框架

文章目录 UI自动化基础什么是UI自动化测试框架UI自动化测试框架的模式数据驱动测试框架关键字驱动测试框架行为驱动测试框架 UI自动化测试框架的作用UI自动化测试框架的核心思想UI自动化测试框架的步骤UI自动化测试框架的构成UtilsLog.javaReadProperties.Java coreBaseTest.ja…

屏幕录制软件有哪些?强烈推荐5款免费好用录屏软件

录制全屏视频是制作视频教程、评论、游戏等内容的绝佳方式。它可以包括您计算机屏幕上的任何活动以及您的音频和网络摄像头。特别是&#xff0c;屏幕录像机对喜欢创建软件评论的视频博主很有帮助。如果您是其中之一&#xff0c;那么好消息是您可以在网络上找到很多屏幕录制应用…

纯c++简易的迷宫小游戏

一个用c写的黑框框迷宫 适合新手入门学习 也适合大学生小作业 下面附上代码 总体思路 初始化游戏界面&#xff1a;设置迷宫的大小&#xff08;WIDTH和HEIGH&#xff09;&#xff0c;生成迷宫地图&#xff08;map&#xff09;&#xff0c;包括墙壁、空地、起点和终点。显示…

怿星科技测试实验室获CNAS实验室认可,汽车以太网检测能力达国际标准

2023年12月27日&#xff0c;上海怿星电子科技有限公司测试实验室&#xff08;下称&#xff1a;EPT LABS&#xff09;通过CNAS实验室认可批准&#xff0c;并于2024年1月5日正式取得CNAS实验室认可证书&#xff08;注册号CNAS L19826&#xff09;&#xff0c;标志着怿星科技的实验…

SpringBoot3自动配置原理

​​​​​​自动配置 遵循约定大约配置的原则&#xff0c;在boot程序启动后&#xff0c;起步依赖中的一些bean对象会自动注入到ioc容器 看一下我们前面写的代码有没有达到自动配置的效果呢&#xff1f; 没有自动&#xff0c;我们写了配置类&#xff0c;写了Import注解&#…

一台电脑如何通过另一台联网电脑访问网络

电脑A没有连接网络&#xff0c;电脑B已经连接wifi。 电脑A如何通过访问电脑B从而连接网络&#xff1f; 1. 将这2台电脑用网线直连 2. 电脑B打开【网络和Internet设置】 3. 右键点击WLAN&#xff0c;选择属性&#xff0c;进入共享tab页面&#xff0c;勾选【允许其他网络用户通过…

超融合之道:亚信安慧AntDB 8.0版本引领数据库创新

在当今多变的数据应用场景中&#xff0c;AntDB作为行业领先的超融合流式实时数仓&#xff0c;秉承着“融合实时”的研发理念&#xff0c;全面应对企业日益复杂的数据处理需求。通过SQL接口访问多种执行引擎&#xff0c;AntDB在实现交易、分析等多重能力的“超融合”方面取得了显…

nacos配置yml空格报错提示

错误格式 正确格式 spring:redis: # redis配置host: 192.168.30.113 # IPport: 6379 # 端口password: # 密码connect-timeout: 10s # 连接超时时间lettuce: # lettuce redis客户端配置pool: # 连接池配置max-active: 8 # 连接池最大连接数&#xff08;使用负值表示没有限…

android studio设置gradle和gradle JDK版本

文章目录 1.gradle JDK版本2.gradle版本 1.gradle JDK版本 file -> project structure -> SDK Location -> Gradle Settings -> Gradle JDK -> Download JDK 2.gradle版本 file -> project structure -> Project

打造创新的金融数据平台,加速数字化和智能化转型丨PingCAP 官网金融行业专区上线

自诞生以来&#xff0c;TiDB 的原生分布式架构在强一致性、高可用性和可扩展性等方面与金融级业务需求高度契合&#xff0c;早期版本即为包括北京银行在内的金融用户提供服务。 TiDB 的核心能力始终源自与中国金融用户的共同创造。作为金融级分布式数据库&#xff0c;TiDB 在国…

东南亚潜力巨大,下一个变现增长点!Flat Ads助力休闲游戏出海

近年来,得益于庞大的消费市场和人口红利,东南亚经济飞速发展,尤其在移动互联网和数字经济领域表现亮眼。巨大的发展空间吸引了众多出海者布局,而东南亚有利的人口结构、不断增长的财富以及日益城市化的人口为数字经济的未来增长奠定了基础。那么,2024年游戏出海东南亚,是否仍有…