二叉树遍历(递归与迭代)

C语言 二叉树的遍历(前中后序递归与迭代遍历,层序迭代遍历) 如图所示二叉树 先序遍历结果为:1 2 4 5 3 6中序遍历结果为:4 2 5 1 6 3后序遍历结果为:4 5 2 6 3 1层序遍历结果为:1 2 3 4 5 6递归的实现就是每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。而迭代法遍历的原理就是模拟递归。 一、先序遍历 递归遍历 迭代遍历 二、中序遍历 迭代遍历 阅读详情

二叉树遍历算法分为前序(PreOredr),中序(InOrder),后序(PostOrder)遍历。并且可以设计递归型或者迭代型算法。

        本文二叉树定义为:

struct BinaryTreeNode
{
	int m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
};

1.二叉树的递归遍历算法

1.1前序遍历
void PreOrder(BinaryTreeNode* pRoot)
{
	if (pRoot!=NULL)
	{
		visit(*pRoot);//visit只是代表处理,关键的是结构
		PreOrder(pRoot->m_pLeft);
		PreOrder(pRoot->m_pRight);
	}	
}
1.2中序遍历
void InOrder(BinaryTreeNode* pRoot)
{
	if (pRoot!=NULL)
	{
		InOrder(pRoot->m_pLeft);
		visit(*pRoot); //visit只是代表处理,关键的是结构
		InOrder(pRoot->m_pRight);
	}	
}
1.3后续遍历
void PostOrder(BinaryTreeNode* pRoot)
{
	if (pRoot!=NULL)
	{
		PostOrder(pRoot->m_pLeft);
		PostOrder(pRoot->m_pRight);
		visit(*pRoot);//visit只是代表处理,关键的是结构
	}	
}

二叉树的三种遍历代码都很简洁,但是这里只是描述结构。根据相应的应用进行设计的时候按照这个结构写递归算法就可以了。关于递归算法顺便提一句很浅显但是设计算法的时候易忽略的一点。二叉树的递归肯定是有底层的叶节点向根节点进行的。

1.4习题举例

       输入一棵二叉搜索树,将该二叉搜索树转换为一个排序的双向链表。要求不能创建任何新的结点,只能调整树中指针的指向。


分析:因为是二叉搜索树所以转变的过程就是节点的左指针指向左子树的最大值,又指针指向右子树的最小值。可以用中序遍历的算法结构来编程。


错误解法:

BinaryTreeNode* findMin(BinaryTreeNode* pNode)
{
	if (pNode==NULL)
		return NULL;
	BinaryTreeNode* min=pNode;
	while (min->m_pLeft!=NULL)
		min=min->m_pLeft;
	return min;
}
BinaryTreeNode* findMax(BinaryTreeNode* pNode)
{
	if (pNode==NULL)
		return NULL;
	BinaryTreeNode* max=pNode;
	while (max->m_pRight!=NULL)
		max=max->m_pRight;
	return max;
}
//从本质上看,这个根本就不是一个二叉树递归算法
void ConvertNode(BinaryTreeNode* pNode)
{
	if (pNode==NULL)
		return;
	BinaryTreeNode* leftNode=pNode->m_pLeft;
	BinaryTreeNode* rightNode=pNode->m_pRight;//保存下次迭代的值
	pNode->m_pLeft=findMax(leftNode);
	//反向的指针如何处理?如果对叶节点也设置反向的指针的话,那么就是一个无限循环
	pNode->m_pRight=findMin(rightNode);
	ConvertNode(leftNode);
	ConvertNode(rightNode);
}
BinaryTreeNode* Convert(BinaryTreeNode* pRootOfTree)
{
	if(pRootOfTree==NULL)
		return NULL;
	BinaryTreeNode* pFirstOfList=findMin(pRootOfTree);//直接找到最小值
	ConvertNode(pRootOfTree);
	return pFirstOfList;
}

正确解法:

BinaryTreeNode* Convert(BinaryTreeNode* pRootOfTree)
{
if(pRootOfTree==NULL)
	return NULL;
	BinaryTreeNode *pLastNodeInList = NULL;
    ConvertNode(pRootOfTree, &pLastNodeInList);
    // pLastNodeInList指向双向链表的尾结点,
    // 我们需要返回头结点
    BinaryTreeNode *pHeadOfList = pLastNodeInList;
    while(pHeadOfList != NULL && pHeadOfList->m_pLeft != NULL)
        pHeadOfList = pHeadOfList->m_pLeft;
    return pHeadOfList;
}

void ConvertNode(BinaryTreeNode* pNode, BinaryTreeNode** pLastNodeInList)
{
    if(pNode == NULL)
        return;
    BinaryTreeNode *pCurrent = pNode;
	//visit_begin
    if (pCurrent->m_pLeft != NULL)
        ConvertNode(pCurrent->m_pLeft, pLastNodeInList);
    pCurrent->m_pLeft = *pLastNodeInList; 
    if(*pLastNodeInList != NULL)
        (*pLastNodeInList)->m_pRight = pCurrent;
    *pLastNodeInList = pCurrent;
    //visit_end
	if (pCurrent->m_pRight != NULL)
        ConvertNode(pCurrent->m_pRight, pLastNodeInList);
}

2.二叉树的迭代遍历算法

为了把一个递归过程改为非递归过程,就需要自己维护一个辅助栈结构,记录遍历时的回退路径。非递归的快速排序的设计依据也是这个。

2.1前序遍历的非递归算法
#include<stack>
void PreOrder(BinaryTreeNode* pRoot)
{
	if (pRoot==NULL)
		return;
	std::stack<BinaryTreeNode*> S;
	BinaryTreeNode *p=pRoot;   //二叉树分左右,所以光有栈不行,合理的运用遍历指针是关键之一
	while(p!=NULL)
	{
		visit(p);
		if (p->m_pRight!=NULL)
			S.push(p->m_pRight);
		if (p->m_pLeft!=NULL)
			p=p->m_pLeft;
		else
		{
			if (S.empty())
				break;
			p=S.top();
			S.pop();
		}
	}
}

2.2中序遍历的非递归算法
#include<stack>
void InOrder(BinaryTreeNode* pRoot)
{
	if (pRoot==NULL)
		return;
	std::stack<BinaryTreeNode*> S;
	BinaryTreeNode *p=pRoot;
	do 
	{
		while(p!=NULL)
		{
			S.push(p);
			p->m_pLeft;
		}
		//若进行到这里左子树为空
		if (!S.empty())//Stack不空时退栈,然后访问该元素
		{
			p=S.top();
			S.pop();
			visit(p);
			p=p->m_pRight;
		}
	} while (p!=NULL||!S.empty());
	//这里的p==NULL表示右子树为空,然后堆栈如果也空的话,才是处理完毕
}

2.3后序遍历的非递归算法

        迭代后序遍历比较复杂。在遍历完左子树时还不能访问根节点,需要再遍历又子树。待右子树遍历完后才访问根节点。所以在辅助栈工作记录中必须注明节点是在左子树还是在右子树。

//记住二叉树后序遍历的非递归调用需要用pair类型,因为需要记录是左进还是右进,所以每个节点必然会进栈两次!!!
void PostOrder(BinaryTreeNode* pRoot)
{
	if (pRoot==NULL)
		return;
	std::pair<BinaryTreeNode*,char> w;
	std::stack<std::pair<BinaryTreeNode*,char> > S;
	BinaryTreeNode *p=pRoot;      
	do 
	{
		while(p!=NULL)           //左子树经过节点加L进栈
		{
			w.first=p;
			w.second='L';
			S.push(w);
			p=p->m_pLeft;
		}
		bool continuel=true;     //继续循环标志,用于L改为R的时候就开始向右遍历
		while (continuel && !S.empty()) //用一个break语句也能实现循环标志continuel的功能
		{
			w=S.top();
			S.pop();
			p=w.first;
			if (w.second=='L')  //标记为L表示左子树遍历完
			{
				w.second=='R';
				S.push(w);
				continuel=false;
				p=p->m_pRight;
			}
			else
				visit(p);      //如果标记为R,表示右子树遍历完
		}
	}while (!S.empty());
}








二叉树理论基础 递归遍历 迭代遍历 统一迭代 层序遍历 int val;大家会发现二叉树的定义 和链表是差不多的,相对于链表 ,二叉树的节点里多了一个指针, 有两个指针,指向左右孩子。这里要提醒大家要注意二叉树节点定义的书写方式。二叉树是一种基础数据结构,在算法面试中都是常客,也是众多数据结构的基石。本篇我们介绍了二叉树的种类、存储方式、遍历方式以及定义,比较全面的介绍了二叉树各个方面的重点,帮助大家扫一遍基础。 阅读详情

相关推荐

二叉树的递归和迭代遍历方法总结

本文归纳学习总结自Carl大佬的公众号代码随想录关于二叉树的几篇推文。如若侵权,请联系删除!其中一篇推文链接 二叉树是一种重要的数据结构,在应用和面试中经常出现,这里对二叉树的几种遍历方法进行了总结。 总的来说二叉树的遍历分为深度遍历,广度遍历,方法也有迭代法和递归法。递归法易于理解,但一定要掌握迭代法。 深度遍历 深度遍历主要包括前序遍历、中序遍历和后序遍历,前中后都是指的节点的访问次序。 图引自代码随想录 1.递归方法 写递归主要是把握住以下三个步骤: 1.确定递归函数的参数和返回值:确定那些参数需要

HFGD2019的博客 805

二叉树的四种遍历方式

中序遍历 二叉树的中序遍历就是首先遍历左子树,然后访问当前节点,最后遍历右子树。对于下面的二叉树,中序遍历结果如下: 直观来看,二叉树的中序遍历就是将节点投影到一条水平的坐标上。如图: 二叉树结构 struct treenode { int val; treenode *left; treenode *right; treenode() : val(0), left(nullptr), right(nullptr) {} treenode(in

weixin_42127177的博客 9779

win11 labelme 汉化菜单

【代码】win11 labelme 汉化菜单。

一直记录 1169

二叉树的遍历

二叉树的遍历.

涛涛的个人博客 1万+

从内外参推导IPM变换方程及代码实现(生成AVM环视拼接图)

最近想实现AVM拼接,看了不少博客和论文,不过比较愚钝,一直没能很好理解原理,尤其是怎么在实现时把下文中Z1和Z2消除的,所以严谨的推导了一下对应的公式,如有不对,水平有限,烦请指出~IPM变换(逆透视变换),顾名思义,即将正常透视效应消除的变换,变换结果为鸟瞰图BEV(俯视图);AVM环视拼接一般是将车身前后左右的四个鱼眼相机拼接成环视图(也是俯视),其使用的单应矩阵将四个相机转到同一个俯视坐标系。

mxdsdo09的博客 4170

DFX从芯片到系统:可制造性、可测试性与可靠性设计实战指南

DFX(Design for eXcellence)是一套面向产品全生命周期的设计方法论,涵盖可制造性(DFM)、可测试性(DFT)、可靠性(DFR)等维度。其核心原理是将制造、测试、维护等环节的约束前置到设计阶段,从而降低流片与量产风险。在芯片与系统硬件领域,DFX不仅是提升良率与测试效率的关键手段,更是保障车规、工控等严苛场景下长期稳定运行的基础。从芯片物理实现到PCB布局,再到系统级散热与维护设计,DFX的落地需要工具链、流程闸门与跨部门协作的体系化支撑。本文基于实际项目经验,分享DFX从设计决策到工

weixin_32349093的博客 349

二叉搜索树的构建以及遍历

二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势;所以应用十分广泛,例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作。二叉查找树(Binary Search Tree),又称为二叉搜索树,二叉排序树。2、二叉搜索树的前序遍历。3、二叉搜索树的中序遍历。4、二叉搜索树的后序遍历。5、二叉搜索树的层序遍历。1、二叉搜索树的构建。...

weixin_47382783的博客 1264

DDR4协议规范之(一)DDR4结构和寻址

DDR4 SDRAM结构和寻址DDR4 SDRAM的封装和寻址新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 DDR4 SDRAM的封装和寻址 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习

YJFeiii的博客 3万+

二叉树(二叉查找树)的遍历(前中后序),添加,查找,删除,节点个数等基础操作,java实现及代码演示。

二叉树是一种常用的树结构。对于树,我们称每一个节点的子节点个数为度;二叉树就是任意一个度小于等于2树,也就是说,二叉树中任意节点的子节点个数小于等于2;二叉查找树是指按照一定规则次序排列的二叉树,这种二叉树左子树的任意节点的值小于当前节点,右子树的任意节点的值大于当前节点,二叉查找树中不能有重复数据。这是我通过随意数据画出的二叉查找树,之后的操作都将用这组数据作为测试;

m0_74000465的博客 1084

SAP ERP 物料主数据同步外围系统

w_input-beskz = i_marc_new-beskz."采购类型 " BESKZ--- ADD BY HX_FHJ 20210106。w_input-beskz = lw_marc-beskz."采购类型 " BESKZ--- ADD BY HX_FHJ 20210106。w_input-sobsl = i_marc_new-sobsl."特殊采购类型-虚拟物料标识。

ChampaignWolf的专栏 1744

【漆学军】MT4进阶到MT5速成之路(2)获取持仓

MT5在持仓获取上,要比MT4复杂些,分两部分,获取持仓和挂单采用了不同的方法。 一、获取持仓中的buy和sell单 int b=0;//获取buy单个数 int s=0;//获取sell单个数 double lot_total_buy=0;//获取持仓中buy单的总手数 double lot_total_sell=0;//获取持仓中sell单的总手数 for(int i=0; i<PositionsTotal(); i++) { ulong ticket=Positi

漆学军的编程笔记 1623

最全二叉树:完整详解二叉树的遍历以及完全二叉树等6种二叉树

二叉树:就是每个节点都只能有两个子节点的树结构,俗称 “大裤衩”,特别形象。通常子树被称作“左子树”(left subtree)和“右子树下图你一看就秒懂了。通过上述的介绍,已经对于二叉树有了初步的认识。本篇文章介绍的基础知识希望读者能够牢牢掌握,并且能够在脑海中建立一棵二叉树的模型,为后续学习数据结构与算法打好基础。

jjc4261的博客 1557

双有源桥DC-DC变换器:原理、软开关与移相控制深度解析

隔离型DC-DC变换器是电力电子系统的核心部件,通过高频变压器实现电气隔离与电压匹配,保障系统安全与灵活适配。其工作原理基于功率半导体器件的开关动作,通过调制策略控制能量传输。该技术的核心价值在于实现高效、高功率密度的电能转换,并支持双向能量流动,这对于提升系统整体能效和运行灵活性至关重要。在新能源储能、电动汽车V2G及数据中心供电等场景中,双向能量流成为刚性需求,推动了如双有源桥等先进拓扑的应用。本文聚焦于双有源桥这一实现高效双向隔离变换的“明星”方案,深入剖析其利用移相控制实现软开关的机理。通过分析谐振

weixin_34195142的博客 378

代码随想录 | 05 二叉树——二叉树的递归遍历、二叉树的迭代遍历

1.递归法 递归三要素 确定递归函数的参数和返回值 确定终止条件 确定单层递归的逻辑 前序遍历思路(后序遍历类似) 根节点非空,传入根节点放入栈中 栈非空时,将栈顶节点弹出 若栈顶节点 A 无孩,从栈中弹出 A 之后,将 A 的值放入数组中; 若 A 有孩子,从栈中弹出 A 之后,将 A 的值放入数组中,并先后将 A 的右孩和左孩压入栈中。 中序遍历迭代法 定义一个指针,一开始指向根节点 root。 当前访问的指针不为空,把当前访问的元素加入栈中,指针一路向左。 当前访问的指针为空,从栈顶 弹出元素,放入

Vvvv_biu的博客 2244

【电动汽车再生制动控制技术(万字长文,图文并茂)】

电动汽车再生制动的基本原理是:通过具有可逆作用的电动机/发电机来实现电动汽车动能和电能的转化。在汽车减速或制动时,可逆电机以发电机形式工作,汽车行驶的动能带动发电机将汽车动能转化为电能并储存在储能器(蓄电池或超级电容器)中;在汽车起动或加速时,可逆电机以电动机形式工作,将储存在储能器中的电能转化为机械能给汽车。这对于改善汽车的能量利用效率,延长电动汽车的行驶距离是至关重要的。

优快云-新能源汽车研发测试专业博主 1575

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

二叉树的递归遍历与迭代遍历(图示)

本文将讲述二叉树递归与迭代的相关知识。

进一步有一步的欢喜 1154

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

二叉树的遍历——递归与迭代

用递归和迭代来实现二叉树的前中后序遍历

2401_82861783的博客 1635

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

二叉树的各种遍历方法(递归,迭代)

可以看出,递归法非常的简单粗暴且明了,前中后序只需要更改几行代码便可实现,这是因为我们可以让左子树,中节点,右子树来按照我们想要的顺序来处理,且互不干扰。

qq_30004513的博客 2113

二叉树遍历(递归和迭代)

此时我们用迭代法写出了二叉树的前后中序遍历,大家可以看出前序和中序是完全两种代码风格,并不像递归写法那样代码稍做调整,就可以实现前后中序。这是因为前序遍历中访问节点(遍历节点)和处理节点(将元素放进result数组中)可以同步处理,但是中序就无法做到同步!

ksidgx的博客 2077

【算法系列-二叉树】二叉树遍历系列(递归+迭代)

欢迎来到【算法系列】第六弹 🏆 二叉树,接下来我们将围绕二叉树这类型的算法题进行解析与练习!一起加油吧!!( •̀ ω •́ )✧✨

Mwt258的博客 2098

二叉树的递归遍历和迭代遍历

二叉树的遍历分为 前序遍历、中序遍历、后序遍历、层次遍历 其实现可以利用递归或者迭代的方法。 递归遍历 这里帮助大家确定下来递归算法的三个要素。每次写递归,都按照这三要素来写,可以保证大家写出正确的递归算法! 确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。 确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构

小菜鸡 699

【二叉树1】二叉树的递归遍历,迭代遍历,统一迭代遍历

【二叉树1】二叉树的递归遍历,迭代遍历,统一迭代遍历

jimaplle的博客 1181

二叉树的递归与迭代遍历

二叉树的递归与迭代遍历 本文将针对二叉树中几种常见的遍历方法进行介绍。 遍历方式 前序遍历 前序遍历首先访问根节点,然后遍历左子树,最后遍历右子树。 中序遍历 中序遍历是先遍历左子树,然后访问根节点,然后遍历右子树。 后序遍历 后序遍历是先遍历左子树,然后遍历右子树,最后访问树的根节点。 递归实现 递归实现二叉树的遍历是非常简单的,其核心就是 深度优先搜索(DFS) 算法。 由于比较简单,...

却把清梅嗅的博客 1245

二叉树中的遍历(迭代与递归)

深度为k,有2^k-1个节点的二叉树。只有度为0和度为2的节点,度=2节点都在同一行完全二叉树:除了最底层节点没填满,其余层节点数达到最大值,最底层节点集中在最左边的位置。如下图二叉搜索树若左子树不为空,左子树上节点都小于根结点的值若右子树不为空,右子树节点都大于根节点的值左右子树也是二叉搜索树平衡二叉树:AVL性质:1)空树;2) 左右子树高度差不超过1;

m0_74301144的博客 760

你还在递归遍历二叉树吗?你要的迭代模板在这里

一、递归法 递归三部曲: 1、确定递归函数的参数和返回值 void recursion(TreeNode *root) 2、确定终止条件 当前节点为空的时候,就返回 if(!root) return; 3、确定单层递归的逻辑 //这里是前序遍历 cout << root->val << endl; preorder(root->left); preorder(root->right); 我们知道,前序遍历二叉树就是【中左右】,中序遍历二叉树就是【左中右】,后序

Janway-Win 480

二叉树的遍历递归与迭代实现

二叉树的遍历 二叉树主要有两种遍历方式: 深度优先遍历:先往深走,遇到叶子节点再往回走。 广度优先遍历:一层一层的去遍历。 那么从深度优先遍历和广度优先遍历进一步拓展,才有如下遍历方式: 深度优先遍历 前序遍历(递归法,迭代法) 中序遍历(递归法,迭代法) 后序遍历(递归法,迭代法) 广度优先遍历 层次遍历(迭代法) 经常会使用递归的方式来实现深度优先遍历,也就是实现前中后序遍历; 迭代:前中后序遍历的逻辑其实都是可以借助栈使用非递归的方式来实现的。 广度优先遍历的实现一般使用队列来实现,这也是队列先进先出

ZZcppc的博客 418
上一篇: 仿函数
下一篇: 模拟循环和递归(if-else)的方法
sicofield
博客等级 码龄18年 169粉丝 169原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值