二叉树非递归遍历(先序、中序、后序)(C++)

1、先序遍历非递归

//先序遍历非递归算法
template<class ElemType>
void NonRecurPreOrder(const BinaryTree<ElemType>& bt, void(*visit)(const ElemType&))
{
	const BinTreeNode<ElemType>* cur = bt.GetRoot();//当前节点
	LinkStack<const BinTreeNode<ElemType>*>s;//栈

	while (cur != NULL)
	{
		//处理当前节点
		(*visit)(cur->data);//访问当前节点
		s.Push(cur);//当前节点入栈

		if (cur->leftChild != NULL)
		{
			//cur的先序序列后继为cur->leftChild
			cur = cur->leftChild;
		}
		else if (!s.Empty())
		{
			//cur的先序序列后继为栈s的栈顶节点的非空右孩子
			while (!s.Empty())
			{
				s.Pop(cur);//取出栈顶节点
				cur = cur->rightChild;//栈顶的右孩子
				if (cur != NULL) break;//右孩子非空即为先序序列后继
			}
		}
		else
		{
			//栈s为空,无先序序列后继
			cur = NULL;//无先序序列后继
		}
	}
}

2、中序遍历非递归

2.1、搜索某节点的最左侧节点

//搜索某节点的最左侧节点
//操作结果:返回以r为根的最左侧的节点,并将搜索过程中的节点加入到栈s中
template<class ElemType>
 const BinTreeNode<ElemType>* GoFarLeft(const BinTreeNode<ElemType>* r, LinkStack<const BinTreeNode<ElemType>*>& s)
{
	if (r == NULL)
	{
		//空二叉树
		return NULL;
	}
	else
	{
		//非空二叉树
		const BinTreeNode<ElemType>* cur = r;//当前节点
		while (cur->leftChild != NULL)
		{
			//cur如果存在左孩子,则cur移向左孩子
			s.Push(cur);//cur入栈
			cur = cur->leftChild;//cur移向左孩子
		}
		return cur;//cur为最左侧节点
	}
}

2.2、中序遍历非递归代码

//中序遍历非递归算法
template<class ElemType>
void NonRecurInOrder(const BinaryTree<ElemType>& bt, void (*visit)(const ElemType&))
{
    const BinTreeNode<ElemType>* cur;//当前节点
	LinkStack<const BinTreeNode<ElemType>*>s;//栈

	cur = GoFarLeft<ElemType>(bt.GetRoot(), s);//cur为二叉树的最左侧的节点
	while (cur!=NULL)
	{
		//处理当前节点
		(*visit)(cur->data);//访问当前节点

		if (cur->rightChild != NULL)
		{
			//cur的中序序列后继为右子树的最左侧的节点
			cur = GoFarLeft(cur->rightChild, s);
		}
		else if (!s.Empty())
		{
			//cur的中序序列后继为栈s的栈顶节点
			s.Pop(cur);//取出栈顶节点
		}
		else
		{
			//栈s为空,无中序序列后继
			cur = NULL;//无中序序列后继
		}
	}
}

3、后序遍历非递归

3.1、修改后的节点结构

//修改后的二叉树节点类模板
template<class ElemType>
struct ModiNode
{
	const BinTreeNode<ElemType>* node;//指向节点

	bool rightSubTreeVisited;//是否右子树已被访问
};

3.2、搜索某节点的最左侧节点

//返回以r为根的二叉树最左侧的被修改后的节点,并将搜索过程中的被修改后的节点加入到栈s中
template<class ElemType>
ModiNode<ElemType>* GoFarLeft(const BinTreeNode<ElemType>* r, LinkStack<ModiNode<ElemType>*>& s)
{
	if (r == NULL)
	{
		//空二叉树
		return NULL;
	}
	else
	{
		//非空二叉树
		const BinTreeNode<ElemType>* cur = r;//当前节点
		ModiNode<ElemType>* newPtr;//被修改后的节点
		while (cur->leftChild!=NULL)
		{
			//cur存在左孩子,则cur移向左孩子
			newPtr = new ModiNode<ElemType>;
			newPtr->node = cur;//指向节点
			newPtr->rightSubTreeVisited = false;//表示右子树未被访问
			s.Push(newPtr);//nodePtr入栈
			cur = cur->leftChild;//cur移向左孩子
		}
		newPtr = new ModiNode<ElemType>;
		newPtr->node = cur;//指向节点
		newPtr->rightSubTreeVisited = false;//表示右子树未被访问
		return newPtr;//newPtr为最左侧的被修改后的节点
	}
}

3.3、后序遍历非递归代码

//后序遍历二叉树非递归
template<class ElemType>
void NonRecurPostOrder(const BinaryTree<ElemType>& bt, void (*visit)(const ElemType&))
{
	ModiNode<ElemType>* cur;//当前被搜索点
	LinkStack<ModiNode<ElemType>*>s;//栈

	cur = GoFarLeft<ElemType>(bt.GetRoot(), s);//cur为二叉树最左侧的被修改后的节点

	while (cur!=NULL)
	{
		//处理当前节点
		if (cur->node->rightChild == NULL || cur->rightSubTreeVisited)
		{
			//当前节点右子树为空或右子树已被访问
			(*visit)(cur->node->data);//访问当前节点
			delete cur;//释放空间

			if (!s.Empty())
			{
				//栈非空,则栈顶元素将指示下一次需要访问的节点
				s.Pop(cur);//出栈
			}
			else
			{
				//栈空,遍历完毕
				cur = NULL;
			}
		}
		else
		{
			//当前节点右子树未被访问
			cur->rightSubTreeVisited = true;//下一次出现在栈顶时的右子树已被访问
			s.Push(cur);//入栈
			cur = GoFarLeft<ElemType>(cur->node->rightChild, s);//搜索右子树最左侧的节点
		}

	}

}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GT-一二

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值