树的先序遍历、中序遍历、后序遍历、层次遍历的非递归算法

Written by Robert_Wang in Southwest University of Science And Technology.

这里提出用非递归遍历的原因是:用递归遍历虽然方便,但是不能递归太深,否则会 stack overflow

先序遍历这里有两种遍历方法

void PreOrder1(Btree*b)
{
	stack<node*>s;
	Btree *p;
	//if (b) s.push(b);
	if (b)
	{
		while (b || !s.empty())
		{
			while (b)
			{
				cout << b->data << " ";
				s.push(b);
				b = b->lchild;
			}
			if (!s.empty())
			{
				p = s.top();
				s.pop();
				if (p->rchild) s.push(p->rchild);
			}
		}
	}
}
void PreOrder2(Btree*b)
{
	stack<Btree*>s;
	Btree *p;
	if (b)
	{
		s.push(b);
		while (!s.empty())
		{
			p = s.top();
			s.pop();
			cout << p->data << " ";
			if (p->rchild) s.push(p->rchild);
			if (p->lchild) s.push(p->lchild);
		}
	}
}

中序遍历只需要在上面的代码的基础上稍作改动

//中序遍历的非递归遍历
void InOrder(Btree*b)
{
	Btree*p;
	stack<Btree*>s;
	if (b)
	{
		while (b || !s.empty())
		{
			while (b)
			{
				s.push(b);
				b = b->lchild;
			}
			if (!s.empty())
			{
				p = s.top();
				s.pop();
				cout << p->data << " ";
				if (p->rchild) s.push(p->rchild);
			}
		}
	}
}

后续遍历就要先走到最左端,再看右儿子是否为空或者已经被访问过

如果没有访问过,转向右子树,循环退一层,继续走到最左端,

如果访问过或者为空,则访问该根结点元素,退栈一次

//后序遍历的非递归算法
void PostOrder(Btree*b)
{
	Btree*p,*r;
	stack<Btree*>s;
	p = b;
	bool flag;
	do
	{
		while (p)
		{
			s.push(p);
			p = p->lchild;
		}
		r = NULL;
		flag = true;//flag == true 表示正在处理栈顶结点
		while (!s.empty() && flag)
		{
			p = s.top();
			if (p->rchild == r)//如果右子树为空或者已经被访问过
			{
				cout << p->data << " ";
				s.pop();
				r = p;
			}
			else
			{
				p = p->rchild;
				flag = false;
			}
		}

	} while (!s.empty());
}

层次遍历就是一个BFS算法

    

void LevelOrder(Btree*b)
{
	queue<Btree*>q;
	Btree*p;
	if (b)
	{
		q.push(b);
		while (!q.empty())
		{
			p = q.back();
			q.pop();
			cout << p->data << " ";
			if (p->lchild) q.push(p->lchild);
			if (p->rchild) q.push(p->rchild);
		}
	}
}

和在一起就是

#include<iostream>
#include<stack>
#include<queue>
using namespace std;
typedef struct node
{
	int data;
	struct node *lchild;
	struct node *rchild;
}Btree;
//非递归算法
void PreOrder1(Btree*b)
{
	stack<node*>s;
	Btree *p;
	//if (b) s.push(b);
	if (b)
	{
		while (b || !s.empty())
		{
			while (b)
			{
				cout << b->data << " ";
				s.push(b);
				b = b->lchild;
			}
			if (!s.empty())
			{
				p = s.top();
				s.pop();
				if (p->rchild) s.push(p->rchild);
			}
		}
	}
}
void PreOrder2(Btree*b)
{
	stack<Btree*>s;
	Btree *p;
	if (b)
	{
		s.push(b);
		while (!s.empty())
		{
			p = s.top();
			s.pop();
			cout << p->data << " ";
			if (p->rchild) s.push(p->rchild);
			if (p->lchild) s.push(p->lchild);
		}
	}
}
//中序遍历的非递归遍历
void InOrder(Btree*b)
{
	Btree*p;
	stack<Btree*>s;
	if (b)
	{
		while (b || !s.empty())
		{
			while (b)
			{
				s.push(b);
				b = b->lchild;
			}
			if (!s.empty())
			{
				p = s.top();
				s.pop();
				cout << p->data << " ";
				if (p->rchild) s.push(p->rchild);
			}
		}
	}
}
//后序遍历的非递归算法
void PostOrder(Btree*b)
void PostOrder(Btree*b)
{
	Btree*p,*r;
	stack<Btree*>s;
	p = b;
	bool flag;
	do
	{
		while (p)
		{
			s.push(p);
			p = p->lchild;
		}
		r = NULL;
		flag = true;//flag == true 表示正在处理栈顶结点
		while (!s.empty() && flag)
		{
			p = s.top();
			if (p->rchild == r)//如果右子树为空或者已经被访问过
			{
				cout << p->data << " ";
				s.pop();
				r = p;
			}
			else
			{
				p = p->rchild;
				flag = false;
			}
		}

	} while (!s.empty());
}
//层次遍历
void LevelOrder(Btree*b)
{
	queue<Btree*>q;
	Btree*p;
	if (b)
	{
		q.push(b);
		while (!q.empty())
		{
			p = q.back();
			q.pop();
			cout << p->data << " ";
			if (p->lchild) q.push(p->lchild);
			if (p->rchild) q.push(p->rchild);
		}
	}
}
void CreateTree(Btree*&b)
{
	b = new Btree;
	b->lchild = b->rchild = NULL;
	int x;
	cin >> x;
	if (x != 0)
	{
		b->data = x;
		CreateTree(b->lchild);
		CreateTree(b->rchild);
	}
	else b = NULL;
}
int main()
{
	Btree*b;
	CreateTree(b);
	cout << "先序遍历算法1如下:" << endl;
	PreOrder1(b);
	cout << "先序遍历算法2如下:" << endl;
	PreOrder2(b);
	cout << "中序遍历算法如下:" << endl;
	InOrder(b);
	cout << "后序遍历的算法如下:" << endl;
	PostOrder(b);
	cout << "层次遍历的算法如下:" << endl;
	LevelOrder(b);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40883132/article/details/79997278