数据结构 - 二叉树非递归遍历

news2024/11/14 8:31:33

文章目录

  • 前言
    • 一、前序
    • 二、中序
    • 三、后序


前言

本文实现二叉树的前中后的非递归遍历,使用栈来模拟递归。
文字有点简略,需要看图和代码理解

树节点:

typedef char DATA;
//树节点
typedef struct Node
{
	DATA data;	//数据
	struct Node* left;	//左子树
	struct Node* right;	//右子树
	bool ok;	//判断完成左子树遍历 ,用于后序遍历
	Node(DATA d)
	{ data = d;
	left = right = NULL;
	ok = true;
	}
}Node;

手搓树:

/构建树
void Tree::Achievements()
{
	Node*  p1 = new Node('a');

	Node* p2 = new Node('b');

	Node* p3 = new Node('c');

	Node* p4 = new Node('d');

	Node* p5 = new Node('e');


	p1->left = p2;
	p1->right = p3;
	p2->right = p4;
	p3->left = p5;

	this->root = p1;
}

一、前序

前序遍历:先根后左右子树
我们通过栈来模拟递归过程:
根据栈的特点:先进先出,所以我们先然右子树进栈再让左子树进栈,这样就符合前序遍历了
代码实现:

//前序遍历 : 根 -> 左子树 -> 右子树
void Tree::Preamble()
{
	//利用栈实现
	stack<Node*> sta;
	//判断是否为空
	if (this->root == NULL)
	{
		return;
	}
	//根先入栈
	sta.push(this->root);

	//当栈空时说明已经遍历完了
	while (!sta.empty())
	{
		//取栈顶元素并出栈
		Node* tmp = sta.top();
		sta.pop();
		cout << tmp->data << "->";

		//因为栈的特点:先进先出,所以先压右子树,在压左子树,这样就可以做到先左子树了
		if (tmp->right != NULL)
		{
			sta.push(tmp->right);
		}
		if (tmp->left != NULL)
		{
			sta.push(tmp->left);
		}
	}
}

运行结果:
在这里插入图片描述
图解:
在这里插入图片描述

二、中序

中序遍历:先左子树再根最后右子树
依旧用模拟栈来实现:先让左子树先出完再出根再右子树
代码实现:

//中序遍历 :先左子树,再根,最后右子树
void Tree::MediumOrder()
{
	//判断是否为空
	if (this->root == NULL)
	{
		return;
	}
	//栈
	stack<Node*> sta;
	//先进根
	sta.push(this->root);
	Node* tmp = this->root;

	//出循环条件
	while (!sta.empty()&&tmp!=NULL)
	{
		//左不为空就进左
		if (tmp->left != NULL)
		{
			sta.push(tmp->left);
			tmp = tmp->left;
		}
		//直到左为空了,开始出栈
		else if (tmp->left == NULL)
		{
			//取栈顶并出栈
			tmp = sta.top();			
			sta.pop();
			cout << tmp->data << "->";

			//右子树为空就说明这个子树遍历完了,可以回到上一级根了(栈顶元素),再判断其右子树是否为空
			while (!sta.empty()&&tmp->right == NULL)
			{
				tmp = sta.top();
				cout << tmp->data << "->";
				sta.pop();
			}
			//右子树不为空进栈,并作为新的根,再往下走
				sta.push(tmp->right);
				tmp = tmp->right;
		}
	}
}

运行结果:
在这里插入图片描述
图解:
在这里插入图片描述

三、后序

后序:先左子树再右子树最后根
还是用栈来模拟,但是在树节点加了一个bool变量来判断是否走完左子树了,判断为假的话就该走右子树了。

代码实现:

后序遍历:左子树再右子树最后根
void Tree::Postscript()
{
	//判断是否为空
	if (this->root == NULL)
	{
		return;
	}
	//栈
	stack<Node*> sta;
	//先让根入栈
	Node* tmp = this->root;
	sta.push(tmp);
	
	//从根的左节点开始
	tmp = tmp->left;

	while (!sta.empty() || tmp != NULL)
	{
		//不为空就继续进栈,直到为空
		while (tmp != NULL)
		{
			sta.push(tmp);
			tmp = tmp->left;
		}

		//左子树为空,取栈顶元素并出栈
		tmp = sta.top();
		sta.pop();

		//判断为真改变为假再入栈
		if (tmp->ok)
		{
			tmp->ok = false;
			sta.push(tmp);
			//栈顶元素为ok假了,该走右了
			tmp = tmp->right;
		}
		//假,将栈顶往下为假的元素都出,直到为真的再重新走
		else
		{   
			cout << tmp->data << "->";
			//遍历到根节点了
			if (tmp == this->root)
			{
				return;
			}
			else
				tmp = NULL;
		}
	}
	}

运行结果:
在这里插入图片描述

图解:

在这里插入图片描述

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

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

相关文章

MySQL进阶-----Linux系统安装MySQL

目录 前言 一、准备工作 1. 准备一台Linux服务器 2. 下载Linux版MySQL安装包 3. 上传MySQL安装包 二、安装操作指令 1. 创建目录,并解压 2.安装mysql的安装包 三、开启mysql与密码修改 1.启动MySQL服务 2. 查询自动生成的root用户密码 3.修改root用户密码 四、创…

【LeetCode】升级打怪之路 Day 26:回溯算法 — 集合划分问题

今日题目&#xff1a; 698. 划分为k个相等的子集 | LeetCode473. 火柴拼正方形 | LeetCode 参考文章&#xff1a; 经典回溯算法&#xff1a;集合划分问题 目录 LC 698. 划分为k个相等的子集 【classic&#xff0c;有难度】数据预处理&#xff1a;计算 target基本回溯优化 1&…

限时免费!Unity 资源商店威尔房间精品资源等你来领!

Unity 资源商店威尔房间精品资源分享 资源介绍资源特色免费领取 Unity 商店资源&#xff1a;Will’s Room Environment, Dormitory Room Environment 免费获取。 资源介绍 好消息来啦&#xff01;Unity 资源商店的威尔房间精品资源正在限时免费中&#xff01;这是一个非常受欢迎…

一维前缀和一维差分(下篇讲解二维前缀和二维差分)(超详细,python版,其他语言也很轻松能看懂)

本篇博客讲解一维前缀和&#xff0c;一维差分&#xff0c;还会给出一维差分的模板题&#xff0c;下篇博客讲解 二维前缀和&二维差分。 一维前缀和&#xff1a; 接触过算法的小伙伴应该都了解前缀和&#xff0c;前缀和在算法中应用很广&#xff0c;不了解也没有关系&#…

【算法】小强爱数学(迭代公式+数论取模)

文章目录 1. 问题2. 输入3. 输出4. 示例5. 分析6. 思路7. 数论&#xff0c;取模相关公式8. 数论&#xff0c;同余定理9. 代码 1. 问题 小强发现当已知 x y B xyB xyB以及 x y A xyA xyA时,能很轻易的算出 x n x_ {n} xn​ y n y_ {n} yn​ 的值.但小强想请你在已知A和B的…

【No.16】蓝桥杯动态规划下|线性DP装箱问题|计数DP0/1背包的方案数|过河卒|完全背包小明的背包2|最长公共子序列|蓝桥骑士|推荐练习题(C++)

线性DP&#xff0c;0/1背包简化版&#xff0c;装箱问题 【题目描述】有一个箱子容量为V(正整数&#xff0c; 0 ≤ V ≤ 20000 0 \le V \le 20000 0≤V≤20000)&#xff0c;同时有n个物品( 0 < n ≤ 30 0 < n \le 30 0<n≤30)&#xff0c;每个物品有一个体积(正整数)。…

ubuntu20.04安裝輸入法

文章目录 前言一、操作過程1、安装fcitx-googlepinyin2、配置language support 前言 參考文獻 一、操作過程 1、安装fcitx-googlepinyin sudo apt-get install fcitx-googlepinyin2、配置language support 第一次點擊進去&#xff0c;會讓你安裝 點擊ctrl和空格切換中英文…

Gin入门指南:从零开始快速掌握Go Web框架Gin

官网:https://gin-gonic.com/ GitHub:https://github.com/gin-gonic 了解 Gin Gin 是一个使用 Go 语言开发的 Web 框架,它非常轻量级且具有高性能。Gin 提供了快速构建 Web 应用程序所需的基本功能和丰富的中间件支持。 以下是 Gin 框架的一些特点和功能: 快速而高效:…

000_coolprop_in_matlab在Matlab中使用CoolProp

在Matlab中使用CoolProp 简介 CoolProp是一个开源的热力学性质库&#xff0c;可以计算多种流体的热力学性质。CoolProp支持多种编程语言&#xff0c;包括Python、C、Matlab等。本文将介绍如何在Matlab中使用CoolProp。 CoolProp官网 本文所使用的Matlab版本为R2021a。 在Ma…

Zabbix与Prometheus区别简述

Zabbix与Prometheus区别简述 历史沿革 一、监控工具简介 1、Zabbix https://www.zabbix.com/cn/download Zabbix是传统的监控系统&#xff0c;出现比云原生早&#xff0c;使用的是SQL关系型数据库&#xff1b;开源监控软件&#xff0c;遵守 GPLv2开源协议&#xff0c;起源于…

为什么说 C/C++ 不适合做 Web 开发?

Web开发是当今信息技术领域的重要组成部分&#xff0c;涉及创建、维护和优化供浏览器访问的网站和应用程序。在众多编程语言中&#xff0c;C/C因其高效、灵活和接近硬件的特性而备受推崇&#xff0c;但在Web开发领域&#xff0c;它们并不被视为首选工具。本文将从以下几个方面探…

Linux Sftp和Scp

scp 和 sftp 区别 1 scp 能将远程文件复制到另一个远程机&#xff0c;sftp 不能。sftp为 SSH的其中一部分&#xff0c;是一种传输档案至 Blogger 伺服器的安全方式 2.scp 没有删除/创建远程目录功能&#xff0c;sftp 有。scp 在需要进行验证时会要求你输入密码或口令。 3. FT…

【算法】回溯与深搜

方法论 1.构建决策树 2.设计代码&#xff1a;全局变量、dfs函数 3.剪枝&#xff0c;回溯 全排列 给定一个不含重复数字的整数数组 nums &#xff0c;返回其 所有可能的全排列 。可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff…

力扣---随机链表的复制

给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的原节点的值。新节点的 n…

进程和线程的关系与区别

目录&#xff1a; 导言&#xff1a; 正文&#xff1a; 一.进程 1.概念 2.进程控制块&#xff08;Process Control Block&#xff0c;PCB) 3.状态 4.优缺点 二.线程 1.概念 2.线程的设计理由与优点 3.缺点 三.进程与线程的区别与联系 导言&#xff1a; 在现代计算机…

ctf__

title: ctf 2.题目类别 3.题目的细分 4.例题 misc 0x05. 明文攻击 明文攻击是一种较为高效的攻击手段&#xff0c;大致原理是当你不知道一个zip的密码&#xff0c;但是你有zip中的一个已知文件&#xff08;文件大小要大于12Byte&#xff09;时&#xff0c;因为同一个zip压缩…

java数据结构与算法刷题-----LeetCode215. 数组中的第K个最大元素

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 解题思路&#xff1a;时间复杂度O( n n n)&#xff0c;空间复杂度…

大屏可视化综合展示解决方案

1.系统概述 1.1.需求分析 1.2.重难点分析 1.3.重难点解决措施 2.系统架构设计 2.1.系统架构图 2.2.关键技术 2.3.接口及要求 3.系统功能设计 3.1.功能清单列表 3.2.数据源管理 3.3.数据集管理 3.4.视图管理 3.5.仪表盘管理 3.6.移动端设计 3.1.系统权限设计 3.…

STM32 CAN的位时序和波特率

STM32 CAN的位时序和波特率 位时序 STM32的CAN外设位时序中只包含3段&#xff0c;分别是同步段SYNC_SEG、位段BS1及位段BS2&#xff0c;采样点位于BS1及BS2段的交界处。其中SYNC_SEG段固定长度为1Tq&#xff0c;而BS1及BS2段可以在位时序寄存器CAN_BTR设置它们的时间长度&…

CISP 4.2备考之《安全支撑技术》知识点总结

文章目录 第一节 密码技术第二节 标识和身份鉴别技术第三节 访问控制技术 第一节 密码技术 密码学发展阶段&#xff1a;古典、近代、现代和公钥密码学及特点。 密码系统组成&#xff1a;明文、加密、密钥、解密、密文。 柯克霍夫原则&#xff1a;密钥保密&#xff0c;算法公开…