二叉树遍历--非递归统一方式

二叉树的遍历

二叉树的遍历方式细分可以成为6种,但是一般约定左节点先于右节点,那么可以合并为3中,根据根节点的访问顺序,分为前序遍历、中序遍历、后续遍历,递归模板主要分为一下情况::

struct TreeNode{
	int val;
	TreeNode *left;
	TreeNode *right;
}
//前序遍历
void preVisite(TreeNode *root)
{
	if(root==NULL) return;
	//前序访问
	print(root->val);
	preVisit(root->left);
	preVisit(root->right);
}

//中序遍历
void midVisite(TreeNode *root)
{
	if(root==NULL) return;
	preVisit(root->left);
	//中序访问
	print(root->val);
	
	preVisit(root->right);
}

//后序遍历
void postVisite(TreeNode *root)
{
	if(root==NULL) return;
	preVisit(root->left);
	preVisit(root->right);
	//后序访问
	print(root->val);
}

对于这些递归模式,要牢记于心,很多二叉树的问题都是基于二叉树的遍历,选择合适的遍历顺序,能够极大的提高算法的效率。

非递归遍历二叉树

递归遍历二叉树,具有很好的模板特性,本质是函数栈的调用,为了在迭代形式下访问二叉树,就需要借助自建的数据栈来保存数据。
很多时候,非递归二叉树遍历没有固定的模板,尤其针对中序遍历和后续遍历,因为执行顺序和访问顺序不同,所以就显得十分麻烦。这里采用统一方法–在访问节点后面添加空指针,show the code now

前序遍历

前序遍历的非递归模式,有一个非常简单的方式(因为执行顺序和访问顺序相同)
简单模式如下:

//
//前序遍历-
void preVisite(TreeNode *root)
{
	if(root==NULL) return;
	stack<TreeNode *> treeStack;
	treeStack.push(root);;
	while(!treeStack.empty())
	{
		TreeNode *cur = treeStack.top();
		treeStack.pop();
		print(cur->val);
		if(cur->right) treeStack.push(cur->right);
		if(cur->left) treeStack.push(cur->left);
	}
}

统一模式如下:
统一模板的重点在于:先将root压入辅助栈,在主循环中,每次判断当前的栈顶节点,如果不是NULL节点,那么需要将这个节点弹出后,在该节点后压入一个NULL,这样保证每个节点都会压入一个NULL节点,同时要注意出了辅助的NULL节点,不会有其他的NULL节点,所以在压入当前节点的左右孩子的时候要注意判断左右孩子是不是NULL节点。

//借助null--压入栈的顺序完全相反   右-左-中
//前序遍历-
void preVisite(TreeNode *root)
{
	if(root==NULL) return;
	stack<TreeNode *> treeStack;
	treeStack.push(root);;
	while(!treeStack.empty())
	{
		TreeNode *cur = treeStack.top();//延迟弹出
		if(cur!=NULL)
		{
			treeStack.pop();
			if(cur->right) treeStack.push(cur->right);//右
			if(cur->left) treeStack.push(cur->left);//左
			treeStack.push(cur);//中
			treeStack.push(NULL);//下一次就可以访问这个节点
		}
		else//开始访问
		{
			treeStack.pop();//弹出空
			print(treeStack.top());
			treeStack.pop();//访问后弹出来
		}
	}
}

中序遍历

//借助null--压入栈的顺序完全相反   右-中-左
//中序遍历-
void inVisite(TreeNode *root)
{
	if(root==NULL) return;
	stack<TreeNode *> treeStack;
	treeStack.push(root);;
	while(!treeStack.empty())
	{
		TreeNode *cur = treeStack.top();//延迟弹出
		if(cur!=NULL)
		{
			treeStack.pop();
			if(cur->right) treeStack.push(cur->right);//右
			treeStack.push(cur);//中
			treeStack.push(NULL);
			if(cur->left) treeStack.push(cur->left);//左孩子是NULL的时候才会开始访问
		}
		else//开始访问
		{
			treeStack.pop();//弹出空
			print(treeStack.top());
			treeStack.pop();//访问后弹出来
		}
	}
}

后续遍历

//借助null--压入栈的顺序完全相反   中-右-左
//后序遍历-
void postVisite(TreeNode *root)
{
	if(root==NULL) return;
	stack<TreeNode *> treeStack;
	treeStack.push(root);;
	while(!treeStack.empty())
	{
		TreeNode *cur = treeStack.top();//延迟弹出
		if(cur!=NULL)
		{
			treeStack.pop();
			treeStack.push(cur);//中
			treeStack.push(NULL);
			if(cur->right) treeStack.push(cur->right);//右
			if(cur->left) treeStack.push(cur->left);//左孩子是NULL的时候才会开始访问
		}
		else//开始访问
		{
			treeStack.pop();//弹出空
			print(treeStack.top());
			treeStack.pop();//访问后弹出来
		}
	}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值