两种常见的方式实现二叉树的中序遍历

二叉树的遍历常见的分为三种方式:前序遍历、中序遍历、后序遍历。简单的理解,所谓的前、中、后的不同实际上就是访问根节点时机的不同。

本文默认的树的结构如下表示:

typedef struct _BiNode
{
	int data;
	struct _BiNode *Lchild, *Rchild;

}Binode, *BiTree;
一、

对于树的遍历操作,常见的方式是采用递归的形式,此处不详细介绍递归。常见的采用递归实现中序遍历的思想就是在判断完输入的树的节点符合函数要求后,优先调用便利函数访问左子树,在访问打印根节点,最后再递归调用函数访问右子树。代码如下:

//中序遍历
bool InOrder(Binode *root)
{
	if (root == NULL)
	{
		return false;
	}
	else
	{
		InOrder(root->Lchild);<span style="white-space:pre">		</span>//<span style="font-family: Arial, Helvetica, sans-serif;">首先访问左子树</span>
		cout << root->data << endl;<span style="white-space:pre">	</span>//访问根节点
		InOrder(root->Rchild);<span style="white-space:pre">		</span>//访问右子树
		return true;
	}
}
二、

下面说一种不常用的方式——不采用递归。中序遍历,顾名思义,根节点要在中间访问,但不能保证是不是第几次经过的时候访问。举例来说,第一次经过根节点并不访问而在左子树访问完毕第二次经过根节点的时候才进行节点数据的访问。所以,符合先经过后访问,后经过先访问的特点。那么,很明显,这个特点比较适合用栈结构来实现。毕竟栈最大的特点就是先入后出,后入先出。

在不考虑栈结构与代码实现的前提下,本文选择了调用STL库中的栈来实现。

中序遍历要从左子树“最左”的节点开始访问。那么我们第一个任务就是找到这个结点:在这个过程中,我们把所有的有左子树的节点入栈,直至找到第一个没有左子树的结点。代码如下:

BiNode *GoFarLeft(BiNode *T, stack<BiNode *> &s)
{
	if (T == NULL)
	{
		return NULL;
	}
	while (T->lchild)
	{
		s.push(T);
		T = T->lchild;
	}
	return T;
}
1在找到了“最左”的节点以后,我们就可以开始遍历工作。

2.1首先,“最左”的节点此时必定没有左子树,那么此节点就是“本地”的根节点,因为中序遍历的特点,默认地访问并打印这个结点。

2.2其次,中序遍历最后访问的是右子树,那么此时应该访问“最左”结点的右子树,有两种结果:(1)存在右子树,那么为了判断右子树中的节点是否还继续拥有左节点,则应调用上方的函数继续查找此处的“最左”结点,即重复步骤1,直至找到不存在右子树的节点为止。(2)如若不存在右子树,那么在已经访问完左、根节点的前提下,可以认定这个结点已经访问完毕。

2.3回退,将栈顶元素打印出栈,此节点为“最左”节点的根节点,接着访问右子树,重复步骤1.

3.重复执行上述操作后即可遍历完毕根节点的整个左子树,打印根节点,再次同样步骤遍历右子树,直到栈中元素为空且没有右子树位置。

代码如下:

void InOrder(BiNode *T)
{
	stack<BiNode *> s;
	//步骤1:一直往左走,找到中序遍历的起点
	BiTree t = GoFarLeft(T, s);
	while (t)
	{
		printf("%d ", t->data); //中序遍历打印

		//如果t节点有右子树,那么重复步骤1
		if (t->rchild != NULL)
		{
			t = GoFarLeft(t->rchild, s);
		}
		//如果t没有右子树,根据栈顶指示,访问栈顶元素
		else if (!s.empty())
		{
			t = s.top();
			s.pop();
		}
		//如果t没有右子树,并且栈为空 
		else
		{
			t = NULL;
		}
	}
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值