二叉树--非递归的 先,中,后 序遍历

二叉树–非递归的 先,中,后 序遍历

题目描述

给定一颗二叉树的逻辑结构如下图,(先序遍历的结果,空树用字符‘#’表示,例如AB#C##D##),建立该二叉树的二叉链式存储结构,并输出该二叉树的先序遍历、中序遍历和后序遍历结果。

输入

  • 第一行输入一个整数t,表示有t个二叉树
  • 第二行起输入每个二叉树的先序遍历结果,空树用字符‘#’表示,连续输入t行。

输出

  • 输出每个二叉树的先序遍历、中序遍历和后序遍历结果。

样例输入

2
AB#C##D##
AB##C##

样例输出
ABCD
BCAD
CBDA
ABC
BAC
BCA

思路:

借助一个栈
一开始先让根节点进栈,然后while(栈非空)
每次循环我们就做这几件事情:

  • 取栈顶元素 tp
  • 如果 tp 为空指针,那么直接将 tp 弹出,continue 进行下一次循环
  • 如果 tp 不空,判断 tp 的 visited 标志是多少
  • 如果是 0, 那么 tp 的左孩子进栈, visited += 1
  • 如果是 1, 那么 tp 的右孩子进栈, visited += 1
  • 如果是 2, 那么 tp 弹出栈

先序遍历,非递归 图示:

初始状态:我们需要把根节点进栈
此时栈中只有一个元素 A
这是初始的状态

取出栈顶的元素(红色框表示),我们第一个访问的是A
然后因为A是第一次访问,我们将A的左孩子进栈,visited ++
我们第一个访问的是A

取出栈顶的元素(红色框表示)B, 这次我们访问B
B也是第一次访问,输出B,B左孩子(NULL)进栈,visited ++
在这里插入图片描述

这一次栈顶元素是 NULL,直接弹出,然后 continue 掉
在这里插入图片描述

弹出了NULL之后栈顶元素又是B了,因为是第二次访问了(对应 visited = 1, 图中把visited +1 之后变为2了),把B的右孩子进栈
在这里插入图片描述

这里栈顶是B的右孩子也就是C,visited = 0,我们将他++
第一次访问,因为是先序,我们输出C,然后将C的左孩子进栈
在这里插入图片描述
栈顶为C的左孩子NULL,直接弹出
在这里插入图片描述

这里栈顶元素又是C了,第二次访问C,C的右孩子进栈
在这里插入图片描述

栈顶元素为C的右孩子NULL,直接弹出
在这里插入图片描述

弹出了C的右孩子之后栈顶元素又是C了,此时C是第三次被访问到,说明C的左右孩子都访问过了,这时候可以弹出C了
在这里插入图片描述

弹出了C之后栈顶元素为B,此时B也是第三次被访问,弹出B
在这里插入图片描述

弹出B之后栈顶为A,A是第二次被访问,A的右孩子D进栈
在这里插入图片描述

栈顶为D,D是第一次被访问,输出D,然后D的左孩子进栈
在这里插入图片描述

栈顶为D的左孩子NULL,弹出
在这里插入图片描述

栈顶为D,D是第二次被访问,D的右孩子进栈
在这里插入图片描述

D的右孩子NULL,直接弹出
在这里插入图片描述

弹出D的右孩子之后栈顶为D,D是第三次被访问,弹出D
在这里插入图片描述

弹出D之后栈顶为A,A也是第三次被访问了,弹出A,遍历结束
在这里插入图片描述

这种方法,先中后序遍历的不同就是在第几次访问的时候输出
如果是先序,第一次访问就输出
中序:第二次
后序:第三次

先序非递归实现:

#define push push_back 
#define pop pop_back 
#define top back 
void node::DLR()
{	
	deque<node*> s;	// use deque as stack
	
	s.push(this);
	while(!s.empty())
	{
		node* tp = s.top();
		if(tp == NULL)
		{
			s.pop();
			continue;
		}
		
		if(tp->visited == 0)
		{
			cout<<tp->data;
			tp->visited += 1;
			s.push(tp->lchild);
		}
		else if(tp->visited == 1)
		{
			tp->visited += 1;
			s.push(tp->rchild);
		}
		else if(tp->visited == 2)
		{
			s.pop();
		}
	}
}

中序非递归:

void node::LDR()
{	
	deque<node*> s;	// use deque as stack
	
	s.push(this);
	while(!s.empty())
	{
		node* tp = s.top();
		if(tp == NULL)
		{
			s.pop();
			continue;
		}
		
		if(tp->visited == 0)
		{
			tp->visited += 1;
			s.push(tp->lchild);
		}
		else if(tp->visited == 1)
		{
			cout<<tp->data;
			tp->visited += 1;
			s.push(tp->rchild);
		}
		else if(tp->visited == 2)
		{
			s.pop();
		}
	}
}

后序非递归:

void node::LRD()
{	
	deque<node*> s;	// use deque as stack
	
	s.push(this);
	while(!s.empty())
	{
		node* tp = s.top();
		if(tp == NULL)
		{
			s.pop();
			continue;
		}
		
		if(tp->visited == 0)
		{
			tp->visited += 1;
			s.push(tp->lchild);
		}
		else if(tp->visited == 1)
		{
			tp->visited += 1;
			s.push(tp->rchild);
		}
		else if(tp->visited == 2)
		{
			cout<<tp->data;
			s.pop();
		}
	}
}

二叉树结构实现

class node
{
public:
	node();
	node* lchild;	// 左孩子 
	node* rchild;	// 右孩子 
	char data;		// 数据域 
	
	// 清除visited标志,递归 
	void dfs_clear_visit(node* &t);
	int visited;	// 第几次被访问? 
	
	void DLR();		// 先序非递归 
	void LDR();		// 中序非递归
	void LRD();		// 后序非递归
};

node::node()
{
	this->lchild = NULL;
	this->rchild = NULL;
	this->visited = 0;
}

创建二叉树(递归)

#define null_char '#'
void creatTree(node* &t)
{
	char c;
	cin>>c;
	
	if(c != null_char)
	{
		node* nd = new node();
		nd->data = c;
		t = nd;
		
		creatTree(t->lchild);
		creatTree(t->rchild);
	}
}

递归地清除visited访问标志

void node::dfs_clear_visit(node* &t)
{
	if(t != NULL)
	{
		t->visited = 0;
		dfs_clear_visit(t->lchild);
		dfs_clear_visit(t->rchild);
	}
}

完整代码:

#include <iostream>
#include <deque>

using namespace std;

class node
{
public:
	node();
	node* lchild;	// 左孩子 
	node* rchild;	// 右孩子 
	char data;		// 数据域 
	
	//  清楚visited标志,递归 
	void dfs_clear_visit(node* &t);
	int visited;	// 第几次被访问? 
	
	void DLR();		// 先序非递归 
	void LDR();		// 中序非递归
	void LRD();		// 后序非递归
};

node::node()
{
	this->lchild = NULL;
	this->rchild = NULL;
	this->visited = 0;
}

void node::dfs_clear_visit(node* &t)
{
	if(t != NULL)
	{
		t->visited = 0;
		dfs_clear_visit(t->lchild);
		dfs_clear_visit(t->rchild);
	}
}

#define null_char '#'
void creatTree(node* &t)
{
	char c;
	cin>>c;
	
	if(c != null_char)
	{
		node* nd = new node();
		nd->data = c;
		t = nd;
		
		creatTree(t->lchild);
		creatTree(t->rchild);
	}
}

#define push push_back 
#define pop pop_back 
#define top back 
void node::DLR()
{	
	deque<node*> s;	// use deque as stack
	
	s.push(this);
	while(!s.empty())
	{
		node* tp = s.top();
		if(tp == NULL)
		{
			s.pop();
			continue;
		}
		
		if(tp->visited == 0)
		{
			cout<<tp->data;
			tp->visited += 1;
			s.push(tp->lchild);
		}
		else if(tp->visited == 1)
		{
			tp->visited += 1;
			s.push(tp->rchild);
		}
		else if(tp->visited == 2)
		{
			s.pop();
		}
	}
}

void node::LDR()
{	
	deque<node*> s;	// use deque as stack
	
	s.push(this);
	while(!s.empty())
	{
		node* tp = s.top();
		if(tp == NULL)
		{
			s.pop();
			continue;
		}
		
		if(tp->visited == 0)
		{
			tp->visited += 1;
			s.push(tp->lchild);
		}
		else if(tp->visited == 1)
		{
			cout<<tp->data;
			tp->visited += 1;
			s.push(tp->rchild);
		}
		else if(tp->visited == 2)
		{
			s.pop();
		}
	}
}

void node::LRD()
{	
	deque<node*> s;	// use deque as stack
	
	s.push(this);
	while(!s.empty())
	{
		node* tp = s.top();
		if(tp == NULL)
		{
			s.pop();
			continue;
		}
		
		if(tp->visited == 0)
		{
			tp->visited += 1;
			s.push(tp->lchild);
		}
		else if(tp->visited == 1)
		{
			tp->visited += 1;
			s.push(tp->rchild);
		}
		else if(tp->visited == 2)
		{
			cout<<tp->data;
			s.pop();
		}
	}
}

int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		node* t = new node();
		creatTree(t);
		
		t->dfs_clear_visit(t);
		t->DLR();
		cout<<endl;
		
		t->dfs_clear_visit(t);
		t->LDR();
		cout<<endl;
		
		t->dfs_clear_visit(t);
		t->LRD();
		cout<<endl;
	}
	
	return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值