打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
二叉树先序、中序、后序遍历的非递归实现

二叉树先序、中序、后序遍历的非递归实现

在网上看了一些用非递归实现先序中序后序遍历二叉树的代码,都很混乱,while、if各种组合嵌套使用,逻辑十分不清晰,把我也搞懵了。想了大半天,写了大半天,突然开了窍,实际上二叉树的这三种遍历在逻辑上是十分清晰的,所以才可以用递归实现的那么简洁。既然逻辑如此清晰,那么用非递归实现也应该是清晰的。

自认为自己的代码比网上搜到的那些都清晰得多,好理解得多。

稍微解释一下:

先序遍历。将根节点入栈,考察当前节点(即栈顶节点),先访问当前节点,然后将其出栈(已经访问过,不再需要保留),然后先将其右孩子入栈,再将其左孩子入栈(这个顺序是为了让左孩子位于右孩子上面,以便左孩子的访问先于右孩子;当然如果某个孩子为空,就不用入栈了)。如果栈非空就重复上述过程直到栈空为止,结束算法。

中序遍历。将根节点入栈,考察当前节点(即栈顶节点),如果其左孩子未被访问过(有标记),则将其左孩子入栈,否则访问当前节点并将其出栈,再将右孩子入栈。如果栈非空就重复上述过程直到栈空为止,结束算法。

后序遍历。将根节点入栈,考察当前节点(即栈顶节点),如果其左孩子未被访问过,则将其左孩子入栈,否则如果其右孩子未被访问过,则将其右孩子入栈,如果都已经访问过,则访问其自身,并将其出栈。如果栈非空就重复上述过程直到栈空为止,结束算法。

其实,这只不过是保证了先序中序后序三种遍历的定义。对于先序,保证任意一个节点先于其左右孩子被访问,还要保证其左孩子先于右孩子被访问。对于中序,保证任意一个节点,其左孩子先于它被访问,右孩子晚于它被访问。对于后序,保证任意一个节点的左孩子右孩子都先于它被访问,其中左孩子先于右孩子被访问。如是而已。

代码里应该体现得比较清楚。这里不光给出了非递归版本,也给出了递归版本。

#include <iostream>#include <stack> using namespace std; struct TreeNode {	int data;	TreeNode* left;	TreeNode* right;	int flag;}; typedef TreeNode *TreePtr; TreePtr CreateTree(){	TreePtr root = new TreeNode;	cout<<"input the data :\n";	int n;	cin>>n;	if (n == -1)	{		return NULL;	} 	else	{		root->data = n;		root->flag = 0;		root->left = CreateTree();		root->right = CreateTree();	}	return root;} void PreOrderRecursion(TreePtr p){	if (p == NULL)	{		return;	}	cout<<p->data<<" ";	PreOrderRecursion(p->left);	PreOrderRecursion(p->right);} void InOrderRecursion(TreePtr p){	if (p == NULL)	{		return;	}	InOrderRecursion(p->left);	cout<<p->data<<" ";	InOrderRecursion(p->right);} void PostOrderRecursion(TreePtr p){	if (p == NULL)	{		return;	}	PostOrderRecursion(p->left);	PostOrderRecursion(p->right);	cout<<p->data<<" ";} void PreOrderNoRecursion(TreePtr p){	cout<<"PreOrderNoRecursion\n"; 	stack<TreeNode> stk;	TreeNode t = *p;	stk.push(t); 	while (!stk.empty())	{		t = stk.top();		stk.pop();		cout<<t.data<<" "; 		if (t.right != NULL)		{			stk.push((*t.right));		} 		if (t.left != NULL)		{			stk.push((*t.left));		}	}} void InOrderNoRecursion(TreePtr p){	cout<<"InOrderNoRecursion\n"; 	stack<TreeNode> stk;	TreeNode t = *p;	stk.push(t); 	while (!stk.empty())	{		if (stk.top().flag == 0)		{			stk.top().flag++;			if (stk.top().left != NULL)			{				stk.push(*(stk.top().left));			}		}		else		{			t = stk.top();			stk.pop();			cout<<t.data<<" ";			if (t.right != NULL)			{				stk.push(*(t.right));			}		}	}} void PostOrderNoRecursion(TreePtr p){	cout<<"PostOrderNoRecursion\n"; 	stack<TreeNode> stk;	TreeNode t = *p;	stk.push(t); 	while (!stk.empty())	{		if (stk.top().flag == 0)		{			stk.top().flag++;			if (stk.top().left != NULL)			{				stk.push(*(stk.top().left));			}		} 		else if (stk.top().flag == 1)		{			stk.top().flag++;			if (stk.top().right != NULL)			{				stk.push(*(stk.top().right));			}		} 		else		{			cout<<stk.top().data<<" ";			stk.pop();		}	}} int main(){	TreePtr t = CreateTree(); 	cout<<"PreOrderRecursion\n";	PreOrderRecursion(t);	cout<<"\n"; 	cout<<"InOrderRecursion\n";	InOrderRecursion(t);	cout<<"\n"; 	cout<<"PostOrderRecursion\n";	PostOrderRecursion(t);	cout<<"\n"; 	PreOrderNoRecursion(t);	cout<<"\n"; 	InOrderNoRecursion(t);	cout<<"\n"; 	PostOrderNoRecursion(t);	cout<<"\n";}
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
467. 递归和非递归解路径总和问题
更简单的非递归遍历二叉树的方法
【小Y学算法】⚡️每日LeetCode打卡⚡️——40.二叉树的后序遍历
《算法导论》读书笔记之第10章 基本数据结构之二叉树
二叉树的三种遍历方式的非递归和递归实现
C++二叉树结构的建立与基本操作
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服