二叉树遍历完整版整理(含层次与递归非递归实现)

版权声明:引用请加上链接,欢迎评论 https://blog.csdn.net/weixin_40457801/article/details/90349144

数据结构那时二叉树学得不是很深入,理解不够,借这段时间的复习,把二叉树的先序,中序,后序,层次遍历的各种实现重新的理解了一遍,在vs2017上码了一遍,然后我把函数都逐一写进了头文件。

.

其中《大话数据结构》中只讲到了先中后的递归算法,所以我也将他们的非递归版本也想写出来,有始有终,整理下也便于今后的学习。

.
讲到非递归的实现,我们都听过“递归的过程就是出入栈的过程”,所有的递归都可以写成非递归版本,具体都是用栈的push和pop来模拟递归的“有来有回”。统一来说,递归算法换成非递归就是使用栈和回溯的思想来实现。

.

1、先序递归、非递归实现

/*头文件bitree_pre*/
#include <iostream>
#include <stack>
using namespace std;

struct bitreenode {
	int data;
	bitreenode *lchild, *rchild;
};
/*
//也可以这样
typedef struct bitreenode {
	int data;
	bitreenode *lchild, *rchild;
}*bitree;
//下面形参改为bitree root即可
*/
class bitree_preTraverse	
{   
	public:
	//递归法
	void pre_recurrece(bitreenode *root)
	{
		if (root == NULL)
			return;
		cout << root->data << endl;
		pre_recurrece(root->lchild);
			pre_recurrece(root->rchild);
	}

	//非递归法,方法有很多,这里使用较广泛的,可用于先、中序
	//使用栈来进行回溯,遍历完左子树后,回溯逐一遍历右子树
	void pre_unrecurrece(bitreenode *root)
	{   
		stack<bitreenode*> s;
		while (root != NULL || !s.empty())
		{
			if (root != NULL)//完成三步工作,将根节点out出来,压入栈,遍历到最左
			{
				cout << root->data << endl;
				s.push(root);
				root = root->lchild;
			}
			else//到最左后,完成三步工作,读出NULL的前一个,结点已经遍历完pop掉,轮到该根结点右子树
			{
				root = s.top();
				s.pop();
				root=root->rchild;
			}
		}
	}
};

.

2、中序递归、非递归实现

/*头文件bitree_mid*/
#include <iostream>
#include <stack>
using namespace std;

struct bitreenode {
	int data;
	bitreenode *lchild, *rchild;
};
/*
//也可以这样
typedef struct bitreenode {
	int data;
	bitreenode *lchild, *rchild;
}*bitree;
//下面改为bitree root即可
*/
class bitree_midTraverse
{
public:
	//递归法
	void mid_recurrece(bitreenode *root)
	{
		if (root == NULL)
			return;	
		//就换下顺序
		mid_recurrece(root->lchild);
		cout << root->data << endl;
		mid_recurrece(root->rchild);
	}

	//非递归法,方法有很多,这里使用较广泛的,可用于先、中序
	//使用栈来进行回溯,遍历完左子树后,回溯逐一遍历右子树
	void mid_unrecurrece(bitreenode *root)
	{
		stack<bitreenode*> s;
		while (root != NULL || !s.empty())
		{
			if (root != NULL)//完成两步工作,压入栈,遍历到最左
			{
				//先序在这里
				//cout << root->data << endl;
				s.push(root);
				root = root->lchild;
			}
			else
			//到最左后,完成四步工作,
			//读出NULL的前一个,将节点out出来(相对就是左子树),结点已经遍历完pop掉,轮到该根结点右子树
			{
				root = s.top();
				cout << root->data << endl;
				s.pop();
				root = root->rchild;
			}
		}
	}
};

.

3、后序递归与非递归

#include <iostream>
#include <stack>
using namespace std;

struct bitreenode {
	int data;
	bitreenode *lchild, *rchild;
};
/*
//也可以这样
typedef struct bitreenode {
	int data;
	bitreenode *lchild, *rchild;
}*bitree;
//下面改为bitree root即可
*/
class bitree_postTraverse
{
public:
	//递归法
	void post_recurrece(bitreenode *root)
	{
		if (root == NULL)
			return;
		//就换下顺序
		post_recurrece(root->lchild);
		post_recurrece(root->rchild);
		cout << root->data << endl;
	}
	
	/*!!!后序与先、后不一样*/
	//后序遍历的非递归算法较复杂,使用一个栈可以实现,但是过程很繁琐,
	//这里可以巧妙的用两个栈来实现后序遍历的非递归算法
	//注意到后序遍历可以看作是下面遍历的逆过程:即先遍历某个结点,然后遍历其右孩子,然后遍历其左孩子。
	//可参考https://blog.csdn.net/sgbfblog/article/details/7773103
	/*
	
	1、Push根结点到第一个栈s中。
	2、从第一个栈s中Pop出一个结点,并将其Push到第二个栈output中。
	3、然后Push结点的左孩子和右孩子到第一个栈s中。
	4、重复过程2和3直到栈s为空。
	5、完成后,所有结点已经Push到栈output中,且按照后序遍历的顺序存放,直接全部Pop出来即是二叉树后序遍历结果。
	
	*/
	void post_unrecurrece(bitreenode *root)
	{	    
		if (root == NULL)
			return;
		stack<bitreenode*> s1, s2;
		while (!s1.empty())
		{
			bitreenode *tmp= s1.top();
			s2.push(tmp);
			s1.pop();
			if (tmp->lchild)
				s1.push(tmp->lchild);
			if (tmp->rchild)
				s1.push(tmp->rchild);
		}
		while (!s2.empty())
		{
			cout << s2.top() << endl;;
			s2.pop();
		}		
	}
};

.

4、层序遍历

//两个队列来完成层次遍历,q1存前一行,q2存后一行
#include <iostream>
#include <queue>
using namespace std;

struct bitreenode {
	int data;
	bitreenode *lchild, *rchild;
};

class bitree_levelTraverse
{
public:
	
	void levelTravelse(bitreenode *root)
	{
		if (root == NULL) return;
		queue<bitreenode*> q1,q2;
		q1.push(root);
		while (!q1.empty())
		{
			bitreenode *tmp = q1.front();
			q1.pop();
			//在打印q1的同时,将其左右节点存入q2
			if (tmp)
			{    
				cout << tmp->data << endl;
				q2.push(tmp->lchild);
				q2.push(tmp->rchild);
			}
			if (!q1.empty())
			{//swap
				while (!q2.empty())
				{
					q1.push(q2.front());
					q2.pop();
				}
			}

		}
	}
};

猜你喜欢

转载自blog.csdn.net/weixin_40457801/article/details/90349144