二叉树的四种遍历和已知遍历序列还原二叉树(二)

本文深入探讨二叉树的遍历方法,包括先序、中序和后序遍历的递归与非递归算法实现,以及如何利用两种遍历序列还原二叉树结构。适合计算机科学学生和算法爱好者学习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一次讲了二叉树考试中常用的性质,这次说一些实际操作。
二叉树的遍历:按一定规律(顺着某一条搜索路径)访问二叉树中的所有结点,使得每个结点均被访问一次,而且仅被访问一次。访问的类型有很多,如:输出或修改结点的信息等,以下用输出为例。因为二叉树有两个或一个后继元素,所以要规定一下遍历方式。

先(根)序的遍历算法
  若二叉树为空树,则空操作;否则,
(1)访问根结点; visit(T->data);
(2)先序遍历左子树;
(3)先序遍历右子树。

代码实现:

 void pretravl(BiTree T)//先序
{
	if (T != NULL)
	{
		cout << T->date;
		pretravl(T->lchild);
		pretravl(T->rchild);
	}
}

中(根)序的遍历算法
  若二叉树为空树,则空操作;否则,
(1)中序遍历左子树;
(2)访问根结点;
(3)中序遍历右子树。

代码实现:

void medtravl(BiTree T)//中序
{
	if (T != NULL)
	{
		medtravl(T->lchild);
		cout << T->date;
		medtravl(T->rchild);
	}
}

后(根)序的遍历算法
  若二叉树为空树,则空操作;否则,
(1)后序遍历左子树;
(2)后序遍历右子树;
(3)访问根节点。

代码实现:

void behtravl(BiTree T)//后序
{
	if (T != NULL)
	{
		behtravl(T->lchild);
		behtravl(T->rchild);
		cout << T->date;
	}
}

3种遍历算法不同之处仅在于访问根结点、遍历左子树、遍历右子树的先后关系。若不考虑visit()语句,则三种遍历方法完全相同(访问路径是相同的,只是访问结点的时机不同) 。三种遍历算法均是递归算法:二叉树的定义本身就是递归的;递归和栈密切联系:递归过程实际就是对栈的操作过程,可以直接通过对栈的操作,来把递归算法写为非递归算法

【二叉树的非递归形式遍历】(以中序为例)

中序遍历的非递归算法思路
1.初始化一个空栈,指针P从二叉树的根结点开始。
2.如果p不空或栈不空,循环执行以下操作。
  1) 如果p不空,表示到达了一个结点,将结点p入桟,并进入其左子树。
  2) 如果p为空而栈不空,表明已经沿着某条路径走出了二叉树,此时需返回访问这条路径最后经过的结点,而该结点正好被保存在栈的栈顶,因此弹出栈顶元素并让p指向它,接下来访问结点p,然后进入其右子树。
3.算法结束
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码实现:

Status InOrderTraverse( BiTree T, status (*visit)(TElemType e ))
{	
    InitStack( S );
    p = T;
    while( p || !StackEmpty( S ))
    { 
        if( p )// 根指针进栈,遍历左子树
	    {   
		     Push( S, p );
		     p = p->lchild;		
		}
		else // 根指针出栈,访问根结点,遍历右子树
		{    
		     Pop( S, p );
		     if( !(*Visit)( p->data))  return ERROR;
		     p = p->rchild;	// 右子树
		}// else
	 }// while
	 return OK;
  }// InOrderTraverse

二叉树的所有算法都是建立在遍历的基础上的,故二叉树的应用也是以遍历为基础,或者说以遍历为主框架。在应用遍历算法时,不同的问题需要对其中的“访问结点”操作作适当的修改。二叉树的创建和求高度及叶子数在我之前的博客中提到过,在这儿就不说了。

【已知两种遍历序列还原二叉树】
在借助两种已知遍历序列还原二叉树中,必须有一种是中序遍历,因为先序和后序都是确定纵向关系,只有中序是确定横向关系。下面根据例题来讲解一下怎么还原。
例题一:已知先序和中序还原二叉树及求后序遍历序列
在这里插入图片描述
例题二:已知中序和后序还原二叉树及求先序遍历序列
在这里插入图片描述
总结一下:上面两道例题都是先根据先序或后序来确定根节点,在中序中由根节点再划分为两个子树,再通过先序或后序判断出子树的根节点,再在中序中划分为若干个子树,从此来递归地一步一步还原二叉树。
已知一种遍历方法和以这种方法遍历的序列,空节点用特殊符号表示,这种题一般为中序遍历,用这种方法可以直接建立一个二叉树,就是所求的二叉树,在前面博客二叉树的创建的章节中提到过,较为简单,就不赘述了。

### 回答1: 已知二叉树的后序遍历序列,可以通过递归的方式还原二叉树。 具体步骤如下: 1. 后序遍历序列的最后一个元素为二叉树的根节点。 2. 从后序遍历序列的第一个元素开始,找到第一个大于根节点的元素,它之前的所有元素都属于根节点的左子树,之后的所有元素都属于根节点的右子树。 3. 递归处理左子树右子树,直到序列为空或只有一个元素。 举个例子,假设后序遍历序列为[4, 5, 2, 6, 3, 1],那么1就是根节点,[4, 5, 2, 6, 3]就是左子树右子树的后序遍历序列。 接下来,我们可以找到第一个大于1的元素为3,所以[4, 5, 2, 6]是左子树的后序遍历序列,[3]是右子树的后序遍历序列。 继续递归处理左子树右子树,左子树的根节点为3,左子树为空,右子树的根节点为6,左子树为空,右子树为2,左子树为4,右子树为5。 最终还原出的二叉树如下所示: ``` 1 / \ 3 2 / \ 6 5 / 4 ``` ### 回答2: 已知二叉树的后序遍历序列如何还原。 后序遍历二叉树遍历的一种方式,遍历顺序是先遍历左子树,再遍历右子树,最后访问根节点。根据后序遍历序列可以还原出原始的二叉树的结构。方法如下: 1. 首先,找到二叉树的根节点。后序遍历序列的最后一个元素即为根节点。 2. 在后序遍历序列中找到根节点后,可以将后序遍历序列分为两部分:左子树的后序遍历序列右子树的后序遍历序列。 3. 对于左子树的后序遍历序列右子树的后序遍历序列,可以通过递归的方式继续还原出左子树右子树。 4. 递归的终止条件是后序遍历序列为空或只有一个元素,此时可以直接返回该节点。 5. 通过递归还原出左子树右子树后,再将根节点与左子树右子树连接起来,构成完整的二叉树。 以上步骤可以通过递归算法来实现。我们可以定义一个函数,接收后序遍历序列作为输入,返回还原后的二叉树的根节点。 总结起来,还原二叉树的后序遍历序列的步骤是:找到根节点,分隔出左右子树的后序遍历序列,递归还原左右子树,最后连接根节点左右子树。 ### 回答3: 已知二叉树的后序遍历序列如何还原,可以通过递归方法进行。后序遍历的顺序是:左子树,右子树,根节点。所以我们可以从后序遍历序列中找到根节点,然后再划分左子树右子树的序列。 具体步骤如下: 1. 首先,找到根节点。根据后序遍历的顺序,最后一个元素即为根节点的值。 2. 划分左子树右子树的序列。在后序遍历中,根节点之前的序列中,是左子树的元素;根节点之后的序列中,之前的元素是右子树的元素。 3. 对于左子树右子树的序列,分别递归地调用还原二叉树的方法,得到左子树右子树。 4. 将左子树右子树连接到根节点上,形成一棵完整的二叉树。 5. 最后,返回该二叉树。 需要注意的是,如果给定的后序遍历序列为空,则返回空。 总结起来,还原二叉树的后序遍历序列可以通过递归的方法,先找到根节点,然后根据根节点将序列划分为左子树右子树,再递归地调用还原方法,最后将左子树右子树连接到根节点上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值