二叉树前中后层遍历(递归/非递归)(简单易懂(*^ー^))

news2025/6/9 11:48:29

文章目录

  • 二叉树的遍历
    • 1 先序遍历
      • 1.1 递归
      • 1.2 非递归
    • 2 中序遍历
      • 2.1 递归
      • 2.2 非递归
    • 3 后序遍历
      • 3.1 递归
      • 3.2 非递归
    • 4 层序遍历
    • 5 前中后层序完整可运行代码(C++)

二叉树的遍历

1 先序遍历

1.1 递归

先序遍历(Preorder Traversal),即根左右的顺序遍历树。递归代码如下:

void preorder(Btree T)//递归先序遍历
{
	if(T)	//判断结点是否为空
	{
		visit(T);   //访问根结点
		preorder(T->lchild);	//递归遍历左子树
		preorder(T->rchild);	//递归遍历右子树
	}
}

1.2 非递归

对于非递归的先序遍历,借助来辅助。非递归代码如下:

void preorder2(BiTree T){//非递归先序遍历
    InitStack(S);	//初始化栈S
    BiTree p = T;	//p作为遍历指针
    	while(p || !isEmpty(S)){	//栈不空或p非空就继续循环
            if(p){	//一路向左	
                visit(p);	//访问当前结点
                Push(S, p);	//将当期那结点入栈
                p = p->lchild;	//左孩子非空,就一直向左走
            }
            else{
                Pop(S, p);	//栈顶元素出栈
                p = p->rchild;	//向右子树走,p赋值为当前结点的右孩子
            }      
        }	
}

2 中序遍历

2.1 递归

中序遍历(Inorder Traversal),即左根右的顺序遍历树,递归代码如下:

void inorder(BiTree T){	//递归中序遍历
	if(T){
		inorder(T->lchild);
		visit(T);
		inorder(T->lchild);
	}
}

2.2 非递归

对于非递归的中序遍历,借助来辅助。非递归代码如下:

void inorder2(BiTree T){	//非递归中序遍历
	InitStack(S);
	BiTree p = T;
	while(p || !IsEmpty(S)){
		if(p){
			Push(S, p);
			p = p->lchild;	//左
		}
		else{
			visit(p);	//根
			Pop(S, p);
			p = p->rchild;	//右
		}
	}
}

3 后序遍历

3.1 递归

后序遍历(Postorder Traversal),即左右根的顺序遍历树,递归代码如下:

void postorder(BiTree T){
	if(T){
		postorder(T->lchild);
		postorder(T->rchild);
		visit(T);
	}
}

3.2 非递归

对于非递归的后序遍历,借助来辅助。

​ 需要注意的是,后序非递归遍历算法和先序中序非递归遍历算法的思路有一点区别,后序非递归算法在visit一个结点时,需要保证左孩子与右孩子都已被访问,并且左孩子需在右孩子之前被访问(左右根)

于是何时可以visit一个结点,就有了以下 2 种情况:

  1. 该结点的左右孩子均为空
  2. 该结点无右孩子,且左孩子已被访问 or 左右孩子存在且都已被访问

对于判断一个结点是否被访问过,我们可以定义一个指针r来进行辅助。

非递归代码如下:

void postorder2(BiTree T){	//非递归后序遍历
    InitStack(S);
    BiTNode *p = T; 	//注:写成BiTree p = T;也可
    BiTNode *r = NULL;		//注:写成BiTree r = NULL;也可
    while(p || !IsEmpty(S)){
        if(p){
            Push(S, p);
            p = p->lchild;	//左
        }
        else{
            GetTop(S, p);	//查看栈顶元素
            if(p->rchild && p->rchild != r){	//如果右孩子存在且没被访问过
                p = p->rchild;	//右
            }
            else{
                visit(p);	//根
                Pop(S, p);
                r = p;	//记录刚刚访问过的结点
                p = NULL;	//结点访问完,p置空以便继续回溯到其父节点进行后序遍历
            }
        }
    }
}

4 层序遍历

层序遍历(Level Order Traversal),即从上至下,从左到右,一层一层地访问结点:

图1 二叉树的层序遍历

对于二叉树的层序遍历,借助队列来辅助。代码如下:

void levelorder(BiTree T){
    InitQueue(Q);	//初始化辅助队列
    BiTree p;
    EnQueue(Q, T);	//根结点入队
    while(!IsEmpty(Q)){	//队列不为空则循环
        DeQueue(Q, p);	//队头结点出队
        visit(p);	//访问出队的结点
        if(p->lchild != NULL)	//出队结点的左孩子非空
            EnQueue(Q, p->lchild);	//左孩子入队
        if(p->rchild != NULL)	//出队结点的右孩子非空
            EnQueue(Q, p->rchild);	//右孩子入队
    }
}

5 前中后层序完整可运行代码(C++)

#include <iostream>
#include <queue>//引入队列头文件
using namespace std;

typedef struct Bnode	/*定义二叉树存储结构*/
{ char data;
	struct Bnode *lchild,*rchild;
}Bnode,*Btree;

void Createtree(Btree &T)	/*创建二叉树函数*/
{
	//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
	char ch;
	cin >> ch;
	if(ch=='#')
		T=NULL;			//递归结束,建空树
	else{
		T=new Bnode;
		T->data=ch;					//生成根结点
		Createtree(T->lchild);	//递归创建左子树
		Createtree(T->rchild);	//递归创建右子树
	}
}

void preorder(Btree T)//先序遍历
{
	if(T)
	{
		cout<<T->data<<"  ";
		preorder(T->lchild);
		preorder(T->rchild);
	}
}

void inorder(Btree T)//中序遍历
{
	if(T)
	{
		inorder(T->lchild);
		cout<<T->data<<"  ";
		inorder(T->rchild);
	}
}

void posorder(Btree T)//后序遍历
{
	if(T)
	{
		posorder(T->lchild);
		posorder(T->rchild);
		cout<<T->data<<"  ";
	}
}

bool Leveltraverse(Btree T)
{
	Btree p;
	if(!T)
		return false;
	queue<Btree>Q; //创建一个普通队列(先进先出),里面存放指针类型
	Q.push(T); //根指针入队
	while(!Q.empty()) //如果队列不空
	{
		p=Q.front();//取出队头元素作为当前扩展结点livenode
		Q.pop(); //队头元素出队
		cout<<p->data<<"  ";
		if(p->lchild)
			Q.push(p->lchild); //左孩子指针入队
		if(p->rchild)
			Q.push(p->rchild); //右孩子指针入队
	}
	return true;
}

int main()
{
	Btree mytree;
	cout<<"按先序次序输入二叉树中结点的值(孩子为空时输入#),创建一棵二叉树"<<endl;
	Createtree(mytree);//创建二叉树
	cout<<endl;
	cout<<"二叉树的先序遍历结果:"<<endl;
	preorder(mytree);//先序遍历二叉树
	cout<<endl;
	cout<<"二叉树的中序遍历结果:"<<endl;
	inorder(mytree);//中序遍历二叉树
	cout<<endl;
	cout<<"二叉树的后序遍历结果:"<<endl;
	posorder(mytree);//后序遍历二叉树
	cout<<endl;
	cout<<"二叉树的层次遍历结果:"<<endl;
	Leveltraverse(mytree);//层次遍历二叉树
	return 0;
}

输入描述与示例

​ 这段代码包括创建二叉树、先序遍历、中序遍历、后序遍历和层次遍历。输入样例应该是一个字符串,其中每个字符代表一个节点的值,按照先序遍历的顺序输入。当输入字符为“#”时,表示该结点为空。

例如,对于一棵如下所示的二叉树:

    A
   / \
  B   C
 / \   \
D   E   F

输入样例应该是:ABD##E##C#F##。其中,A 是根节点,BA 的左子节点,DB 的左子节点,# 表示 D 的左子节点为空,接下来的 # 表示 D 的右子节点为空,以此类推。

运行结果

图2 代码运行结果

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

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

相关文章

Anaconda3安装配置/创建删除虚拟环境/在特定虚拟环境下安装库

1. Anaconda3彻底卸载 先说Anaconda3的卸载&#xff0c;在Anaconda3安装路径下有一个Uninstall-Anaconda3.exe&#xff0c;右键以“管理员身份运行”&#xff0c;可执行完全卸载 2. 下载与安装Anaconda3 官网地址https://repo.anaconda.com/ 点击Anaconda Distribution&…

自学大数据第14天NoSQL~MongoDB及其命令

这几天主要是看了一下mongodb的一些知识,网上也有一些教程,今天主要是复习一下mongodb 启动mongodb 在连接mongodb前首先要创建数据存放目录与日志存放目录,还得保证当前用户对这两个目录有相应的读写操作 mongod --dbpath/usr/local/mongodb/data/db/ --logpath/usr/lcoal/mon…

(四)【软件设计师】计算机系统—基础单位进制

文章目录一、计算机基础单位二、进制1.进制表示符号2.进制之间的转换&#xff1a;(1)十进制转换为二进制&#xff08;例子&#xff1a;173&#xff09;(2)十进制转换为八进制&#xff08;3&#xff09;十进制转换为十六进制&#xff08;4&#xff09;二进制转换为十进制&#x…

Linux入门 - 最常用基础指令汇总

目录 ls指令 pwd指令 cd指令 touch指令 mkdir指令 rmdir指令 && rm 指令 man指令&#xff08;重要&#xff09; cp指令&#xff08;重要&#xff09; mv指令&#xff08;重要&#xff09; cat指令 more指令 less指令&#xff08;重要&#xff09; head指令…

交换机PCB板布局布线注意事项

由于板卡在工作中会受到各种各样的干扰&#xff0c;这些干扰不仅影响系统运行的稳定性&#xff0c;同时也有可能带来误差&#xff0c;因此考虑如何抑制干扰&#xff0c;提高电磁兼容性是PCB布局布线时的一项重要任务。海翎光电的小编现将PCB布局布线中需要主要考虑的因素列在下…

银行数字化转型导师坚鹏:深度解读《中华人民共和国数据安全法》

深度解读《中华人民共和国数据安全法》 ——中国数据安全立法 助力企业稳健发展课程背景&#xff1a; 很多金融机构存在以下问题&#xff1a; 不清楚数据安全法立法背景&#xff1f; 不知道如何理解数据安全法相关政策&#xff1f; 不清楚如何数据安全进行合规建设&#xf…

【前端之旅】Vue入门笔记

一名软件工程专业学生的前端之旅,记录自己对三件套(HTML、CSS、JavaScript)、Jquery、Ajax、Axios、Bootstrap、Node.js、Vue、小程序开发(Uniapp)以及各种UI组件库、前端框架的学习。 【前端之旅】Web基础与开发工具 【前端之旅】手把手教你安装VS Code并附上超实用插件…

计算机组成原理第二章数据的表示与运算(中)

提示&#xff1a;且行且忘且随风&#xff0c;且行且看且从容 文章目录前言2.2.0 奇偶校验码(大纲已删)2.2.1 电路的基本原理 加法器设计2.2.2 并行进位加法器2.2.3 补码加减运算器2.2.4 标志位的生成2.2.5 定点数的移位运算2.2.62.2.6.1 原码的乘法运算2.2.6.2 补码的乘法运算2…

Linux下异步socket客户端

文章目录socket 客户端1. 创建socketsocket()函数返回值2. 设置socket的属性connect函数sockaddr_in结构体inet_pton函数3. fcntl设置非阻塞4. recv函数socket 客户端 1. 创建socket socket()函数 #include <sys/socket.h> int socket(int domain, int type, int proto…

四、线程安全,synchronized,volatile(JMM)【4/12 5/12 6/12】【多线程】

4. 多线程带来的的风险-线程安全 (重点) 4.1 观察线程不安全 static class Counter {public int count 0;void increase() {count;} } public static void main(String[] args) throws InterruptedException {final Counter counter new Counter();Thread t1 new Thread(()…

数据结构——排序(4)

作者&#xff1a;几冬雪来 时间&#xff1a;2023年4月12日 内容&#xff1a;数据结构排序内容讲解 目录 前言&#xff1a; 1.快速排序中的递归&#xff1a; 2.小区间优化&#xff1a; 3.递归改非递归&#xff1a; 4.归并排序&#xff1a; 5.归并排序的非递归形式&…

Revit中如何绘制倾斜的屋顶及一键成板?

Revit中如何绘制倾斜的屋顶&#xff1f;如下图所示&#xff0c;像这种坡屋顶有两种方法进行绘制。 第一种&#xff1a;定义坡度。 1、点击建筑选项卡中的屋顶按钮。选择使用矩形工具。 2、在选项栏中&#xff0c;偏离值修改为500&#xff0c;把屋顶迹线绘制出来。 3、取消这三…

软件测试今天你被内卷了吗?

认识一个人&#xff0c;大专学历非计算机专业的&#xff0c;是前几年环境好的时候入的行&#xff0c;那时候软件测试的要求真的很低&#xff0c;他那时好像是报了个班&#xff0c;然后入门的&#xff0c;但学的都是些基础&#xff0c;当时的他想的也简单&#xff0c;反正也能拿…

【面试】限流算法有哪些?

文章目录前言1.固定窗口限流算法1.2 固定窗口限流的伪代码实现1.2 固定窗口算法的优缺点2.漏桶算法3.令牌桶算法4. 滑动窗口限流算法4.1 什么是滑动窗口限流算法4.2 滑动窗口限流算法的伪代码实现4.3 滑动窗口限流算法的优缺点漏桶算法 VS 令牌桶算法总结参考 & 鸣谢前言 …

docker项目实施

鲲鹏916架构openEuler-arm64成功安装docker并跑通tomcat容器_闭关苦炼内功的技术博客_51CTO博客鲲鹏916架构openEuler-arm64成功安装docker并跑通tomcat容器&#xff0c;本文是基于之前这篇文章鲲鹏920架构arm64版本centos7安装docker下面开始先来看下系统版本卸载旧版本旧版本…

刘二大人《Pytorch深度学习实践》第八讲加载数据集

文章目录Epoch、Batch-Size、IterationsDataset、DataLoader课上代码torchvision中数据集的加载Epoch、Batch-Size、Iterations 1、所有的训练集进行了一次前向和反向传播&#xff0c;叫做一个Epoch 2、在深度学习训练中&#xff0c;要给整个数据集分成多份&#xff0c;即mini-…

【密码学】ElGamal加密算法原理 以及 例题讲解

目录前言1. 原理2. 例题2.1 例题一2.2 例题二前言 具体的性质&#xff1a; 非对称加密算法应用于一些技术标准中&#xff0c;如数字签名标准&#xff08;DSS&#xff09;、S/MIME 电子邮件标准算法定义在任何循环群 G 上&#xff0c;安全性取决于 G 上的离散对数难题 1. 原理…

元宇宙地产暴跌,林俊杰亏麻了

文/章鱼哥出品/陀螺财经随着元宇宙的兴起&#xff0c;元宇宙地产曾一度被寄予厚望&#xff0c;成为各大投资者追捧的对象。然而&#xff0c;最近的一次元宇宙地产价值暴跌再次提醒我们&#xff0c;高收益背后可能伴随着高风险。根据元宇宙分析平台WeMeta的数据显示&#xff0c;…

400以内的蓝牙耳机哪款好?400以内蓝牙耳机排行榜

谈起TWS&#xff0c;无论是传统的音频厂商还是手机厂商&#xff0c;都是其不可或缺的重要产品线&#xff0c;现在很多许多蓝牙耳机都不是千篇一律得形状&#xff0c;市场也鲜有商家在外观上下功夫&#xff0c;下面分享几款400元以内&#xff0c;内外兼具的耳机品牌。 一、南卡…

Spring boot+Vue3博客平台:修改密码与找回密码的设计与实现

修改密码与找回密码功能的设计与实现涉及到前后端的配合。本文将详细介绍如何通过设计思路、技术实现和代码示例实现这两个功能。 一、修改密码功能 设计思路 在设计修改密码功能时&#xff0c;需要注意以下几点&#xff1a; 用户输入的当前密码需要正确新密码需要满足一定的…