二叉树的先序、中序、后序遍历C++

这篇具有很好参考价值的文章主要介绍了二叉树的先序、中序、后序遍历C++。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、二叉树的结构

二叉树的节点结构如下所示

template<typename T>
struct TreeNode
{
	T data;        //数据
	TreeNode* left;    //指向左孩子节点的指针
	TreeNode* right;   //指向右孩子节点的指针

	TreeNode(T dat, TreeNode* lft = nullptr, TreeNode* rig = nullptr):data(dat), left(lft), right(rig) {}
};

如下所示是一个二叉树,其中的每一个节点都是由上述TreeNode节点的一个具体对象。                                

二叉树的先序,中序,后序遍历,左程云算法课学习笔记,数据结构,c++,数据结构,算法
图1

二、先序遍历、中序遍历、后序遍历

1、什么是先序遍历

先遍历根(父)节点、再遍历左节点、最后遍历右节点。

注意:这里说的遍历并不是行走。毕竟我们能够先取到的指针只有根节点指针,而如果想找一个节点,则一定要先找到它的根节点。这里的遍历指的是“介绍”这棵树的方式。通常来讲,我们是使用的打印的方式“介绍”一棵树的。

所以,先序遍历展开来讲是:如果一棵树上有根节点,则先输出根节点,再输出左孩子节点、最后输出右孩子节点。

例如,上述图1中的二叉树,先序遍历输出是:3、9、20、15、7

2、什么是中序遍历

先遍历输出左孩子节点,再遍历输出根节点,最后遍历输出右孩子节点。

例如,上述图1中的二叉树,中序遍历输出是:9、3、15、20、7

3、什么是后序遍历

先遍历输出左孩子节点,再遍历输出右孩子节点,最后遍历输出根节点

例如,上述图1中的二叉树,后序遍历输出是:9、15、7、20、3

三、三种遍历的递归法

1、二叉树的递归序

首先,我们逐步分析二叉树的递归原理。我们取一个临时指针temp,来在二叉树上行进(根-左-右的顺序),则temp的指向顺序、即二叉树的递归序是:

--START

3(根节点)

9(找到3的左孩子、左子树根节点)

9(找9的左孩子,没有,则回到9)

9(找9的右孩子,没有,则回到9)

3(3的左子树遍历完毕,回到3)

20(3的右子树根节点)

15(20的左孩子)

15(15的左孩子,没有,回到15)

15(15的右孩子,没有,回到15)

20(20的左子树遍历完毕,回到20)

7(20的右孩子)

7(7的左孩子,没有,回到7)

7(7的右孩子,没有,回到7)

20(20的右子树遍历完毕,回到20)

3(3的右子树遍历完毕,回到3)

--END

其中的temp指向其实指的是

上述过程用代码实现如下:

void traversal(TreeNode* root) {
	//1)程序资源在root节点,判空
	if (nullptr == root)
	{
		return;
	}
	//2)遍历左子树
	traversal(root->left);
    //左子树遍历完成,程序资源回到root节点
	//3)遍历右子树
	traversal(root->right);
    //右子树遍历完成,程序资源回到root节点
	return;
}

2、三种遍历的递归法实现

则我们可以看见规律。二叉树的递归序中,每一个节点都会被遍历3次。每个节点,当其作为root节点、左子树遍历完成、右子树遍历完成的时候,程序资源都会回到这个节点。

1)先序遍历的递归法

而先序遍历,则只要在第一次处于这个节点的时候进行输出即可。见下列代码:

void preorderTraversal(TreeNode* root) {
	//根节点为空,直接返回
	if (nullptr == root)
	{
		return;
	}
	//1)输出
	cout << root->val << endl;
	//2)遍历左子树
	preorderTraversal(root->left);
	//3)遍历右子树
	preorderTraversal(root->right);
	return;
}

2)中序遍历的递归法

同理,中序遍历,只要在递归序的基础上,在第二次回到节点时输出即可。见下列代码:

void inorderTraversal(TreeNode* root) {
	//根节点为空,直接返回
	if (nullptr == root)
	{
		return;
	}
	//1)遍历左子树
	inorderTraversal(root->left);
	//2)输出
	cout << root->val << endl;
	//3)遍历右子树
	inorderTraversal(root->right);
	return;
}

3)后序遍历的递归法

同理,后序遍历,只要在递归序的基础上,在第三次回到节点时输出即可。见下列代码:

void postorderTraversal(TreeNode* root) {
	//根节点为空,直接返回
	if (nullptr == root)
	{
		return;
	}
	//1)遍历左子树
	postorderTraversal(root->left);
	//2)遍历右子树
	postorderTraversal(root->right);
	//3)输出
	cout << root->val << endl;
	return;
}

这样理解,二叉树的递归遍历法是不是非常简单了?

四、三种遍历的非递归法

任何递归函数都可以改成非递归函数。我们使用的递归法,其实是系统帮助我们压栈的一个过程。

1、分析解决方案

我们知道栈的特性是先入后出,如果按照一般遍历顺序根节点-左孩子-右孩子进行压栈,则和上述遍历顺序不符

2、三种遍历的非递归实现

1)先序遍历实现

算法步骤:

a、根节点进栈;

b、弹出并输出栈顶节点tp;

c、栈顶节点tp的左孩子进栈、右孩子进栈;

d、重复上述b、c;

代码实现:文章来源地址https://www.toymoban.com/news/detail-608766.html

void preorderTraversal(TreeNode* root) {
	if (nullptr == root)
	{
		return;
	}
	stack< TreeNode*> mstack;
	mstack.push(root);
	while (!mstack.empty())
	{
		//打印栈顶节点
		TreeNode* tp = mstack.top();
		cout << tp->val << endl;
		//弹出节点
		mstack.pop();
		//右孩子节点压栈
		if (nullptr != tp->right)
		{
			mstack.push(tp->right);
		}
		//左孩子节点压栈
		if (nullptr != tp->left)
		{
			mstack.push(tp->left);
		}
	}
	return;
}

2)中序遍历实现

算法步骤:

a、从根节点开始,整棵树的左边界节点依次进栈;

b、弹出并输出栈顶节点tp;

c、栈顶节点tp的右子树左边界节点依次进栈

d、重复上述b、c;

代码实现:

void inorderTraversal(TreeNode* root) {
	TreeNode* tp = root;
	stack< TreeNode*> mstack;
	
	//弹出并输出栈顶节点,并对其右孩子节点压栈
	while (!mstack.empty() || nullptr != tp)
	{
		//左边界节点依次进栈
		if (nullptr != tp)
		{
			mstack.push(tp);
			tp = tp->left;
		}
		else
		{
			//获取栈顶节点指针
			tp = mstack.top();
			//输出
			cout << tp->val << endl;
			//弹出节点
			mstack.pop();

			//如果有右子树,右子树的左边界节点压栈
			tp = tp->right;
		}
	}
	return;
}

3)后序遍历实现

后序遍历即:左-右-根 的顺序。一般来说,我们一定会先行进到根节点,才能找到其左右子树。所以,我们可以想办法获得 根-右-左的节点遍历,再利用栈的特性反序输出。

算法步骤:

申请两个栈,s1,s2

a、根节点入栈s1;

b、弹出(不输出)栈顶节点tp,压入栈s2;

c、栈顶节点tp的左孩子、右孩子依次进栈s1;

d、重复上述b、c,直到栈s1为空,所有节点进入栈s2;

e、依次弹出并输出栈s2栈顶节点;

代码实现:

void postorderTraversal(TreeNode* root) {
	//根节点为空,直接返回
	if (nullptr == root)
	{
		return;
	}
	//申请2个栈
	stack< TreeNode*> s1, s2;
	//根节点压入s1
	s1.push(root);
	while (!s1.empty())
	{
		TreeNode* tp = s1.top();
		s2.push(tp);
		s1.pop();
		if (nullptr != tp->left)
		{
			s1.push(tp->left);
		}
		if (nullptr != tp->right)
		{
			s1.push(tp->right);
		}
	}
	//依次弹出并输出s2节点
	while (!s2.empty())
	{
		cout << s2.top()->val << endl;
		s2.pop();
	}
	return;
}

到了这里,关于二叉树的先序、中序、后序遍历C++的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 十三、数据结构——二叉树的遍历(先序、中序和后序)详细思路和代码

    在数据结构中,二叉树是一种常用且重要的数据结构。二叉树的遍历是指按照一定顺序访问二叉树的所有节点,常见的遍历方式有前序遍历、中序遍历和后序遍历。本文将详细介绍这三种遍历算法,并介绍最优二叉树。 首先,我们先来了解一下二叉树的基本定义。二叉树是每

    2024年02月15日
    浏览(41)
  • 【数据结构】16 二叉树的定义,性质,存储结构(以及先序、后序、中序遍历)

    一个二叉树是一个有穷的结点集合。 它是由根节点和称为其左子树和右子树的两个不相交的二叉树组成的。 二叉树可具有以下5种形态。 一个二叉树第i层的最大结点数为 2 i − 1 2^{i-1} 2 i − 1 , i ≥ 1 i geq 1 i ≥ 1 每层最大结点可以对应完美二叉树(满二叉树),其所有分支结

    2024年02月20日
    浏览(43)
  • Java根据二叉树的先序和后序得到二叉树

    一般情况下,我们会根据先序和后序写出二叉树,但是用代码怎末写呢? 例如: 给定两个整数数组  preorder  和  inorder  ,其中  preorder  是二叉树的 先序遍历 ,  inorder  是同一棵树的 中序遍历 ,请构造二叉树并返回其根节点。 思路:我们先根据先序遍历找到根节点记录

    2024年01月19日
    浏览(35)
  • 数据结构——二叉树先序、中序、后序三种遍历

    先序遍历可以想象为,一个小人从一棵二叉树根节点为起点,沿着二叉树外沿,逆时针走一圈回到根节点,路上遇到的元素顺序,就是先序遍历的结果 先序遍历结果为:A B D H I E J C F K G 动画演示: 记住小人沿着外围跑一圈(直到跑回根节点),多看几次动图便能理解    

    2024年02月11日
    浏览(48)
  • 二叉树先序,中序,后序遍历的非递归算法(一)

    思路: 二叉树的前序遍历过程: 从树根开始沿着左子树一直深入,直到最左端无法深入时,返回; 进入最近深入时遇到结点的右子树,再进行如此的深入和返回; 直到最后从根节点的右子树返回到根节点为止; 由其深入返回的过程我们知道可以用一个栈来帮助我们消除递

    2023年04月14日
    浏览(78)
  • 【树】建立二叉链表存储的二叉树+遍历二叉树(先序、中序、后序、层序)

    二叉树的构建利用了递归的原理,在按先序序列构建二叉树时,为了能让电脑知道每个结点是否有左右孩子,我们要对原二叉树进行 扩展 ,明确表示每个结点的左右孩子,若当前结点没有左右孩子,我们用’#\\\'表示。 由普通二叉树----扩展二叉树,如下图: 此时当我们按先序

    2024年02月07日
    浏览(38)
  • 递归和迭代实现二叉树先序、中序、后序和层序遍历

    递归比较简单,直接上代码: ### 1.1 先序遍历 1.2 中序遍历 1.3 后序遍历 能够用递归方法解决的问题基本都能用非递归方法实现。因为递归方法无非是利用函数栈来保存信息,可以寻找相应的数据结构替代函数栈,同样可以实现相同的功能。下面用栈,类比递归方法来统一实

    2024年01月20日
    浏览(39)
  • 数据结构——二叉树的先中后序遍历

    ——本节内容为Bilibili王道考研《数据结构》P43~P45视频内容笔记。 目录 一、二叉树的先中后序遍历 1.先中后序遍历 2.举例  3.先中后序遍历和前中后缀的关系 4.代码实现 5.求遍历序列 6.应用:求树的深度 二、二叉树的层次遍历 1.层次遍历 2.算法思想: 3.算法演示: 4.代码实

    2024年02月12日
    浏览(39)
  • 力扣(144. 二叉树的前序遍历&&94.二叉树的中序遍历&&145. 二叉树的后序遍历)

    题目链接 题目1: 思路:较简单的思路,就是先将左孩子全部入栈,然后出栈访问右孩子,右孩子为空,再出栈,不为空,右孩子入栈,然后再次循环访问左孩子。 题目链接 题目2: 思路:同前序遍历一样,只不过访问结点,改为出栈时访问。 题目3链接 题目3: 思路1:同样

    2024年01月19日
    浏览(50)
  • 树的前序遍历与中序遍历构造二叉树和树的中序遍历与后序遍历构造二叉树

    目录 一.树的前序遍历与中序遍历构造二叉树 1.题目描述 2.问题分析 3.代码实现 二.树的中序遍历与后序遍历构造二叉树 1.题目描述 2.问题分析 3.代码实现 三.问题思考 给定两个整数数组  preorder 和 inorder  ,其中  preorder 是二叉树的 先序遍历 , inorder  是同一棵树的 中序遍

    2023年04月15日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包