三种使用栈的后序遍历方法

本文探讨了如何利用栈进行后序遍历二叉树的方法,详细阐述了具体步骤和操作要点。

使用栈的后序遍历

第一种:不推荐,比较麻烦。定义一个结构体,增加flag标志。
<span style="font-size:14px;">#ifndef	TRITREE_HEADER
#define TRITREE_HEADER
using namespace std;
#include<stack>
#include<queue>
#include<list>
#include<algorithm>
#include<iterator>
#include<assert.h>
template<class T>
class TNode
{
public:
	TNode() { lchild = rchild = parent = nullptr; };
	T data;
	TNode<T>* lchild, *rchild, *parent;
};

template<class T>
struct FNode//为非递归后序遍历创建的结构体数据
{
	TNode<T>* m_pNode;
	bool m_bflag;
	FNode(TNode<T>* pNode, bool bflag)
	{
		m_pNode = pNode; m_bflag = bflag;
	}
};

template<class T>
void TriTree<T>::PostOrderByflag(TNode<T>* bt)
{
	printf("非递归后序遍历:");
	if (nullptr == bt)
	{
		return;
	}
	stack<FNode<T>> SNode;
	while (nullptr != bt || !SNode.empty())
	{
		while (nullptr != bt)
		{
			//fasle 表示 只遍历过左子树 此时还不能输出根节点
			SNode.push(FNode<T>(bt, false));
			bt = bt->lchild;
		}
		while (!SNode.empty() && SNode.top().m_bflag)
		{
			//true表示 已经遍历过该节点 右子树 可以输出根节点了
			cout << SNode.top().m_pNode->data << " ";
			SNode.pop();
		}
		if (!SNode.empty() && !SNode.top().m_bflag)
		{
			bt = SNode.top().m_pNode;
			SNode.top().m_bflag = true;
			bt = bt->rchild;
		}
	}
	puts("");
}</span>

第二种:使用双栈,将1栈淡弹出元素压入二栈,二栈依次弹出便可以达到后序遍历效果。
template<class T>
void TriTree<T>::PostOrderByDoubleStack(TNode<T>* bt)
{
	if (nullptr == bt)
	{
		return;
	}
	stack<TNode<T>*> Process;
	stack<TNode<T>*> Result;
	TNode<T>* pTemp = nullptr;
	Process.push(bt);
	while (!Process.empty())
	{
		pTemp = Process.top();
		Result.push(pTemp);
		Process.pop();
		if (nullptr != pTemp->lchild)
		{
			Process.push(pTemp->lchild);
		}
		if (nullptr != pTemp->rchild)
		{
			Process.push(pTemp->rchild);
		}

	}
	while (!Result.empty())
	{
		Visited(Result.top());
		Result.pop();
	}
	puts("");
}
第三种:使用单栈,增加一个临时变量标记它的左子树与右字数是否被访问。由于是自底向上,如果临时节点不为当前节点的左孩子或右孩子,那么当前节点左子树与右子树已经被访问。
template<class T>
void TriTree<T>::PosOrderBySingleStack(TNode<T>* bt)
{
	if (nullptr == bt)
	{
		return;
	}
	TNode<T>* pCur = bt;
	TNode<T>* pLast = bt;//初始化 这个一定要注意 从根节点开始
	stack<TNode<T>*> SNode;
	SNode.push(bt);
	while (!SNode.empty())
	{
		pCur = SNode.top();
		if (nullptr != pCur->lchild&&pLast != pCur->lchild
			&&pLast != pCur->rchild)
			//如果当前节点的左孩子或者右孩子 等于 刚刚打印过的节点
			//则当前节点的左子树已经处理 否则就压栈
		{
			SNode.push(pCur->lchild);
		}
		else if (nullptr != pCur->rchild&&pLast != pCur->rchild)
		{
			//如果上一次打印节点 与当前节点右孩子相同 表明右子树已经打印
			SNode.push(pCur->rchild);
		}
		else
		{
			//打印当前节点 更新最近打印节点 弹栈
			SNode.pop();
			Visited(pCur);
			pLast = pCur;
		}
	}
	puts("");
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值