【数据结构】——二叉树的遍历详解

之前写了一篇关于二叉树的概要介绍,里面包括了二叉树的创建等相关代码,这一篇文章主要来详细的对二叉树的创建讲解一下~
参考之前的文章二叉树的概要介绍
首先,定义一下关于二叉树的结点信息

typedef struct BtNode
{
	struct BtNode* leftchild;
	struct BtNode* rightchild;
	ElemType data;
}BtNode, *BinaryTree;

这是篇文章所要分析的树
在这里插入图片描述
接下来进入正题,我们首先为大家呈现的是

一、二叉数的递归遍历

1、二叉树的递归中序遍历

void InOder(struct BtNode* p)
{
	if (p != NULL)
	{
		InOder(p->leftchild);
		printf("%c", p->data);
		InOder(p->rightchild);
	}
}

2、二叉树的递归先序遍历

void PreOder(struct BtNode* p)
{
	if (p != NULL)
	{
		printf("%c", p->data);
		PreOder(p->leftchild);
		PreOder(p->rightchild);
	}
}

3、二叉数的递归后续遍历

void LsOder(struct BtNode* p)
{
	if (p != NULL)
	{
		LsOder(p->leftchild);
		LsOder(p->rightchild);
		printf("%c", p->data);
	}
}

实现原理:
首先进入循环,递归进入结点A的左子树B;再递归进入结点B的左子树C;结点C的左子树为空,则打印结点C,回退到结点B,打印B;接着递归进入结点B的右子树D,结点D的左子树为空,打印结点D,回退到结点B;B的递归完成,回退到A,打印结点A…依次类推。
在这里插入图片描述

二、二叉树的非递归遍历

1、非递归中序遍历

void NiceInOrder(struct BtNode* ptr)
{
	if (ptr == NULL) return;
	stack<struct BtNode*> st;
	while (!st.empty() || ptr != NULL)
	{
		while (ptr != NULL)
		{
			st.push(ptr);
			ptr = ptr->leftchild;
		}
		ptr = st.top(); st.pop();
		cout << ptr->data << " ";
		ptr = ptr->rightchild;
	}
	cout << endl;
}

本代码的关键在于while (!st.empty() || ptr != NULL)这个循环。因为当我们把C入栈过后它的ptr为空,但是这时的栈并不为空,所以再次进入循环;
当把A出栈过后,因为ptr右子树还有没有遍历到的结点,所以ptr != NULL进入循环,循环操作。
2、非递归后序遍历
特点:该结点的左边访问完了右边访问完了才应该打印该结点
所以要有一个标记结点来判定右子树有被访问过没有,如果访问过了就打印该结点。

void NicePastOrder(struct BtNode* ptr)
{
	if (NULL == ptr) return;
	stack<struct BtNode*> st;
	struct BtNode* tag = NULL;
	while (!st.empty() || ptr != NULL)
	{
		while (ptr != NULL)
		{
			st.push(ptr);
			ptr = ptr->leftchild;
		}
		ptr = st.top(); st.pop();
		if (ptr->rightchild == NULL || ptr->rightchild == tag)
		{
			cout << ptr->data << " ";
			tag = ptr;
			ptr = NULL;
		}
		else
		{
			st.push(ptr);
			ptr = ptr->rightchild;
		}
	}
	cout << endl;
}

3、非递归前序遍历
前序遍历只需要先把右子树入栈再把左子树入栈,最后打印即可

void NicePreOrder(struct BtNode* ptr)
{
	if (ptr == NULL) return;
	stack<struct BtNode*> st;
	st.push(ptr);
	while (!st.empty())
	{
		ptr = st.top(); st.pop();
		cout << ptr->data << " ";
		if (ptr->rightchild != NULL)
		{
			st.push(ptr->rightchild);
		}
		if (ptr->leftchild != NULL)
		{
			st.push(ptr->leftchild);
		}
	}
	cout << endl;
}

三、利用栈实现非递归遍历

在这里插入图片描述
1、非递归后序遍历
用数字标记结点入栈次数

struct StkNode
{
	struct BtNode* pnode;
	int popnum;
public:
	StkNode(struct BtNode* p = NULL) :pnode(p), popnum(0) {}
};
void StkNicePastOrder(struct BtNode* ptr)
{
	if (ptr == NULL) return;
	stack<StkNode> st;
	st.push(StkNode(ptr));
	while (!st.empty())
	{
		StkNode node = st.top(); st.pop();
		if (++node.popnum == 3)
		{
			cout << node.pnode->data << " ";
		}
		else
		{
			st.push(node);
			if (node.popnum == 1 && node.pnode->leftchild != NULL)
			{
				st.push(StkNode(node.pnode->leftchild));
			}
			else if (node.popnum == 2 && node.pnode->rightchild != NULL)
			{
				st.push(StkNode(node.pnode->rightchild));
			}
		}
	}
	cout << endl;
}

2、非递归中序遍历

void StkNiceInOrder(struct BtNode* ptr)
{
	if (ptr == NULL) return;
	stack<StkNode> st;
	st.push(StkNode(ptr));
	while (!st.empty())
	{
		StkNode node = st.top(); st.pop();
		if (++node.popnum == 2)
		{
			cout << node.pnode->data << " ";	
		    if (node.pnode->rightchild != NULL)
			{
				st.push(StkNode(node.pnode->rightchild));
			}
		}
		else
		{
			st.push(node);
			if (node.popnum == 1 && node.pnode->leftchild != NULL)
			{
				st.push(StkNode(node.pnode->leftchild));
			}
		
		}
	}
	cout << endl;
}

四、层次遍历

在这里插入图片描述
队列实现。根结点入队,队列不为空就打印,再依次入队左右节点

void LevelOrder(struct BtNode* ptr)
{
	if (NULL == ptr) return;
	queue<struct BtNode*> qu;
	qu.push(ptr);
	while (!qu.empty())
	{
		ptr = qu.front(); qu.pop();
		cout << ptr->data << " ";
		if (ptr->leftchild != NULL)
		{
			qu.push(ptr->leftchild);
		}
		if (ptr->rightchild != NULL)
		{
			qu.push(ptr->rightchild);
		}
	}
	cout << endl;
}

五、“工”字型遍历

在这里插入图片描述
一个栈一个队列共同实现

void LevelOrder2(struct BtNode* ptr)
{
	if (NULL == ptr) return;
	stack<struct BtNode*> qua;
	queue<struct BtNode*> qub;
	qua.push(ptr);
	while (!qua.empty() || !qub.empty())
	{
		while(!qua.empty())
		{   ptr = qua.top(); qua.pop();
			cout << ptr->data << " ";
			if (ptr->rightchild != NULL)
			{
				qub.push(ptr->rightchild);
			}
			if (ptr->leftchild != NULL)
			{
				qub.push(ptr->leftchild);
			}
		}
		while (!qub.empty())
		{
			ptr = qub.front(); qub.pop();
			cout << ptr->data << " ";
			if (ptr->rightchild != NULL)
			{
				qua.push(ptr->rightchild);
			}
			if (ptr->leftchild != NULL)
			{
				qua.push(ptr->leftchild);
			}
		}
	}
	cout << endl;
}
发布了62 篇原创文章 · 获赞 7 · 访问量 2566

猜你喜欢

转载自blog.csdn.net/qq_43412060/article/details/104658551