常见的二叉树遍历方法

这里主要实现了常见的二叉树的几种遍历方法:1) 递归实现的先序、中序、后序遍历; 2) 非递归实现的先序、中序、后序遍历; 3) 层次遍历中包含普通的层次遍历、层次遍历的分行输出、层次遍历的“之”字形输出。

下图是采用的一个二叉树示例图,后续将通过"#"法,先序输入的方式建立二叉树(‘#’表示为空)。再通过上述各种方法遍历输出。

                                                       

先序遍历: 根左右---A B E F C G

中序遍历: 左根右---E B F A G C

后序遍历: 左右根---E F B G C  A

关于递归实现的比较简单,不做说明;

非递归实现中,主要利用了。后序遍历中还需要用到一个辅助指针,指向最近访问的指针;

层次遍历中,主要用到的是队列。之字形遍历需要用到两个栈。具体思路说明可参见代码。

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

//节点
typedef struct BitNode
{
	char data;
	struct BitNode *lchild, *rchild;
}*BiTree;

//按照先序遍历建树   '#'法
void CreateTree(BiTree &T)
{
	//按先序输入节点值,‘#’表示空
	char data;
	cin >> data;
	//cout << data;
	if (data == '#')
		T = NULL;
	else
	{
		T = new BitNode();
		T->data = data;
		CreateTree(T->lchild);  //左子树
		CreateTree(T->rchild);  //右子树
	}
}

/***********递归遍历***********/
void visit(BiTree T)
{
	if (T->data != '#')
		cout << T->data << " ";
}

//先序遍历
void PreOrder(BiTree T)
{
	if (T != NULL)
	{
		visit(T);
		PreOrder(T->lchild);
		PreOrder(T->rchild);
	}
}

//中序
void InOrder(BiTree T)
{
	if (T != NULL)
	{
		InOrder(T->lchild);
		visit(T);
		InOrder(T->rchild);
	}
}

//后序
void LastOrder(BiTree T)
{
	if (T != NULL)
	{
		LastOrder(T->lchild);
		LastOrder(T->rchild);
		visit(T);
	}
}

//非递归
//先序  访问T->data后,将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,再先序遍历T的右子树。
void PreOrder2(BiTree T)
{
	stack<BiTree> stack;
	BiTree p = T;  //p作为遍历指针
	while (p != nullptr || !stack.empty())
	{
		if (p != nullptr)
		{
			cout << p->data << " ";
			stack.push(p);
			p = p->lchild;
		}
		else
		{
			p = stack.top();
			stack.pop();
			p = p->rchild;
		}
	}
}

//中序   T是要遍历树的根指针,中序遍历要求在遍历完左子树后,访问根,再遍历右子树。
//先将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,访问T->data,再中序遍历T的右子树。
void InOrder2(BiTree T)
{
	stack<BiTree> stack;
	BiTree p = T;
	while (p != nullptr || !stack.empty())
	{
		if (p != nullptr)
		{
			stack.push(p);
			p = p->lchild;
		}
		else
		{
			p = stack.top();
			cout << p->data << " ";
			stack.pop();
			p = p->rchild;
		}
	}
}

//后序遍历
void LastOrder2(BiTree T)
{
	stack<BiTree> stack;
	BiTree p = T, help = nullptr;   //r指向最近访问的指针
	while (p != nullptr || !stack.empty())
	{
		if (p)  //先走到最左结点,沿途入栈
		{
			stack.push(p);
			p = p->lchild;
		}
		else
		{
			p = stack.top();
			if (p->rchild && p->rchild != help)
				p = p->rchild;
			else
			{
				cout << p->data << " ";
				stack.pop();
				help = p;
				p = nullptr;
			}
		}
	}
}

//几种不同风格的层次遍历   需要用到队列
//普通的层次遍历直接输出
void LevelOrder(BiTree T)
{
	BiTree p = T;
	queue<BiTree> queue;
	queue.push(p);
	while (!queue.empty())
	{
		p = queue.front();
		cout << p->data << " ";
		queue.pop();
		if (p->lchild)
			queue.push(p->lchild);
		if (p->rchild)
			queue.push(p->rchild);
	}
}

//便于后面两个输出的
void ShowVector(vector<vector<char> > &vec)
{
	int row = vec.size();
	for (int i = 0; i < row; ++i)
	{
		int col = vec[i].size();
		for (int j = 0; j < col; ++j)
			cout << vec[i][j] << " ";
		cout << endl;
	}
}

//分行输出
void LevelOrder1(BiTree T)
{
	vector<vector<char> > vec;
	BiTree p = T;
	queue<BiTree> queue;
	queue.push(p);
	while (!queue.empty())
	{
		int size = queue.size();  //读取每一层的元素的数量
		vector<char> LevelElem;	  //存放一层的值
		while (size--)			  //遍历完一层,队列中正好剩下下一层的所有元素
		{
			p = queue.front();
			LevelElem.push_back(p->data);
			queue.pop();
			if (p->lchild)
				queue.push(p->lchild);
			if (p->rchild)
				queue.push(p->rchild);
		}
		vec.push_back(LevelElem);
	}
	ShowVector(vec);
}

//层次遍历之字形打印
//利用两个栈.打印奇数层,则先保存左结点,再保存右节点到第二个栈里,出栈时即先右后左
//打印偶数层,先保存右节点再保存左结点到第一个栈里
void LevelOrder2(BiTree T)
{
	vector<vector<char> > vec;
	BiTree p = T;
	stack<BiTree> stack1, stack2;
	stack1.push(T);	//根节点,奇数层,压入栈1
	while (!stack1.empty() || !stack2.empty())
	{
		if (!stack1.empty())
		{
			vector<char> tmp;
			while (!stack1.empty())
			{
				p = stack1.top();
				tmp.push_back(p->data);
				stack1.pop();

				if (p->lchild)
					stack2.push(p->lchild);
				if (p->rchild)
					stack2.push(p->rchild);
			}
			vec.push_back(tmp);
		}

		if (!stack2.empty())
		{
			vector<char> tmp;
			while (!stack2.empty())
			{
				p = stack2.top();
				tmp.push_back(p->data);
				stack2.pop();

				if (p->rchild)
					stack1.push(p->rchild);
				if (p->lchild)
					stack1.push(p->lchild);
			}
			vec.push_back(tmp);
		}
	}
	ShowVector(vec);
}


int main()
{
	BiTree T;
	CreateTree(T);
	cout << "*****递归遍历:先序*****" << endl;
	PreOrder(T);
	cout << endl;

	cout << "*****递归遍历:中序*****" << endl;
	InOrder(T);
	cout << endl;
	
	cout << "*****递归遍历:后序*****" << endl;
	LastOrder(T);
	cout << endl;

	cout << "*****非递归遍历:先序*****" << endl;
	PreOrder2(T);
	cout << endl;

	cout << "*****非递归遍历:中序*****" << endl;
	InOrder2(T);
	cout << endl;

	cout << "*****非递归遍历:后序*****" << endl;
	LastOrder2(T);
	cout << endl;

	cout << "*****普通的层次遍历*****" << endl;
	LevelOrder(T);
	cout << endl;

	cout << "*****分行输出的层次遍历*****" << endl;
	LevelOrder1(T);
	cout << endl;

	cout << "*****之字形的层次遍历*****" << endl;
	LevelOrder2(T);
	cout << endl;
	
	system("pause");
	return 0;
}

运行结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值