当前位置: 首页 > news >正文

二叉树的遍历问题

目录

一、二叉树

1、二叉树结点结构

2、递归遍历

3、非递归遍历

①非递归先序遍历

②非递归中序遍历

③非递归后序遍历

4、二叉树的宽度优先遍历

①宽度优先遍历


一、二叉树

1、二叉树结点结构

struct BinaryNode
{
    int val;
    BinaryNode* left;
    BinaryNode*  right;
}

2、递归遍历

①先序遍历:对每一棵树和子树都是先遍历头结点,然后再是左结点,最后是右结点。

②中序遍历:对每一棵树和子树都是先遍历左结点,然后再是头结点,最后是右结点。

③后序遍历:对每一棵树和子树都是先遍历左结点,然后再是右结点,最后是头结点。

void recursion(struct BinaryNode * root)
{
	if (root == NULL)
	{
		return;
	}

	//先序遍历
	printf("%d ", root->val);

	recursion(root->lChild);

	recursion(root->rChild);
}

void recursion(struct BinaryNode * root)
{
	if (root == NULL)
	{
		return;
	}

	recursion(root->lChild);

	//中序遍历
	printf("%d ", root->val);

	recursion(root->rChild);
}

void recursion(struct BinaryNode * root)
{
	if (root == NULL)
	{
		return;
	}

	recursion(root->lChild);

	recursion(root->rChild);

	//后序遍历
	printf("%d ", root->val);
}

 总结:第一次来到结点的时候打印就是先序遍历、第二次来到结点打印就是中序遍历、第三次来到结点打印就是后续遍历

3、非递归遍历

二叉树的非递归遍历需要用到栈容器,下面会对非递归遍历进行详细介绍

①非递归先序遍历

步骤:

(1) 先压入头节点

(2) 从栈中弹出一个结点cur

(3) 打印cur

(4) 先压右结点,再压左结点(如果有)

(5) 重复 (2) --- (4) 直到栈为空

代码如下:

//先序非递归
void prenorecursion(BinaryNode* headnode)
{
	printf("先序遍历:");
	if (headnode)
	{
		stack<BinaryNode*> s;
		s.push(headnode);
		while (s.size())
		{
			//1、弹出栈顶元素
			headnode = s.top();
			s.pop();

			//2、打印
			printf("%d ", headnode->m_Val);

			//3、如果有左右结点,先压入右结点,再压入左结点
			if (headnode->m_RightNode)
			{
				s.push(headnode->m_RightNode);
			}
			if (headnode->m_LeftNode)
			{
				s.push(headnode->m_LeftNode);
			}
		}
	}
}

②非递归中序遍历

中序非递归遍历的思想就是先把左边的结点全部压入到栈,直到为空,然后开始弹出结点并打印,弹出的时候将右边的结点也压入栈,重复上述步骤。

代码如下:

//中序非递归
void midnorecursion(BinaryNode* headnode)
{
	printf("中序遍历:");
	if (headnode)
	{
		stack<BinaryNode*> s;
		while (s.size() || headnode)
		{
			//只要左结点不为空,一直压入栈中
			if (headnode)
			{
				s.push(headnode);
				headnode = headnode->m_LeftNode;
			}
			//左边压完了,弹出结点的同时检查右边是否有结点,如果有,将右边结点压入并重复检测有无左结点
			else
			{
				headnode = s.top();
				printf("%d ", headnode->m_Val);
				s.pop();
				headnode = headnode->m_RightNode;
			}
		}
	}
}

③非递归后序遍历

步骤:

(1) 先压入头结点

(2) 弹出cur,将cur压入收集栈

(3) 先压左结点,再压右结点(如果有)

(4) 重复(2) --- (4) 直到栈为空

(5) 依次弹出收集栈元素并打印

 代码如下:

//后序非递归
void afternorecursion(BinaryNode* headnode)
{
	printf("后序遍历:");
	if (headnode)
	{
		stack<BinaryNode*> s;//容器栈
		stack<BinaryNode*> collectstack;//收集栈
		//1、压入头结点
		s.push(headnode);
		while (s.size())
		{
			//2、弹出栈顶元素,并压入收集栈
			headnode = s.top();
			s.pop();
			collectstack.push(headnode);
			//3、将栈顶元素的左结点、右节点压入栈中(如果有的话)
			if (headnode->m_LeftNode)
			{
				s.push(headnode->m_LeftNode);
			}
			if (headnode->m_RightNode)
			{
				s.push(headnode->m_RightNode);
			}
		}
		//4、当栈中元素为空,依次弹出收集栈中元素并打印
		while (collectstack.size())
		{
			headnode = collectstack.top();
			printf("%d ", headnode->m_Val);
			collectstack.pop();
		}
	}
}

4、二叉树的宽度优先遍历

如何完成二叉树的宽度优先遍历(常见题目:求一颗二叉树的宽度)

①宽度优先遍历

宽度优先遍历上图中就是 1->2->3->4->5->6->7->8->9

算法思想: 使用一个队列(可以是数组或链表)来完成。初始时只有一个根节点,然后每次取出一个结点,就把它的左右儿子(如果有)放入队列。

代码如下:

void treewidth(BinaryNode* headnode)
{
	queue<BinaryNode*> q;
	//1、先放头节点
	q.push(headnode);
	while (q.size())
	{
		//2、弹出结点并打印
		headnode = q.front();
		printf("%d ", headnode->m_Val);
		q.pop();
		//3、放入左结点和右节点(如果有)
		if (headnode->m_LeftNode)
		{
			q.push(headnode->m_LeftNode);
		}
		if (headnode->m_RightNode)
		{
			q.push(headnode->m_RightNode);
		}
	}
}

相关文章:

  • FPGA/HDL 人员开发利器-TerosHDL(开源 IDE)
  • 《谁动了我的奶酪》阅读笔记
  • 2023秋招--腾讯天美--游戏客户端--一面面经
  • 跨模态学习能力再升级,EasyNLP电商文图检索效果刷新SOTA
  • JavaScript 中什么时候使用 Map 更合适(二)
  • 【统计学习|书籍阅读】第五章 决策树 p55-p75
  • 【GlobalMapper精品教程】009:DSM过滤植被和房屋并生成等高线案例教程
  • web前端期末大作业:我的家乡广东(html+css布局)div制作
  • 【C进阶】——内存操作函数memcpy、memmove、memcmp、memset详解及其模拟实现
  • 【DNS服务器的配置】实操
  • mysql索引下推与回表
  • 安装Scala
  • [C#小技巧]如何捕捉上升沿和下降沿
  • 一行代码,将2D转3D图表!
  • C++编程 杨辉三角详解
  • 分享的文章《人生如棋》
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • cookie和session
  • Debian下无root权限使用Python访问Oracle
  • ECMAScript入门(七)--Module语法
  • ERLANG 网工修炼笔记 ---- UDP
  • JS实现简单的MVC模式开发小游戏
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • node入门
  • Protobuf3语言指南
  • Spark学习笔记之相关记录
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 首页查询功能的一次实现过程
  • 我看到的前端
  • 运行时添加log4j2的appender
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • #define,static,const,三种常量的区别
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (1)常见O(n^2)排序算法解析
  • (3)(3.5) 遥测无线电区域条例
  • (Mac上)使用Python进行matplotlib 画图时,中文显示不出来
  • (poj1.3.2)1791(构造法模拟)
  • (层次遍历)104. 二叉树的最大深度
  • (分布式缓存)Redis分片集群
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统
  • (十一)图像的罗伯特梯度锐化
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • (转)德国人的记事本
  • ***linux下安装xampp,XAMPP目录结构(阿里云安装xampp)
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .NET 程序如何获取图片的宽高(框架自带多种方法的不同性能)
  • .net 使用ajax控件后如何调用前端脚本
  • /dev下添加设备节点的方法步骤(通过device_create)
  • @property python知乎_Python3基础之:property
  • [BUG] Hadoop-3.3.4集群yarn管理页面子队列不显示任务
  • [C#]猫叫人醒老鼠跑 C#的委托及事件
  • [C#C++]类CLASS