高级数据结构 | 二叉树遍历 —非递归遍历,判断结点引用次数进行优先深度遍历 ...

在此之前,对非递归先序遍历还有一种新的思路,具体方法如下:

非递归先序遍历

此方法类似于非递归实现的快排,利用栈的先进后出特性,在其中一个元素没有完全断绝关系前,下一个元素绝没有机会出栈。同时,这种方法与二叉树的层次遍历有异曲同工之妙,只不过层次遍历使用的数据结构为队列。
在这里插入图片描述
如上图,在出栈时判断结点是否有左右孩子,有则每次先将右孩子入栈,再将左孩子入栈。同时出栈时每次都先出左孩子的结点,如果左孩子有子节点将继续入栈。如此一来就可以实现先遍历完左子树再遍历右子树的需求。

其中,灰色框出的为每次出栈的栈顶元素,而红色箭头代表此结点引入的两个新结点,绿色部分代表此结点没有孩子,没有引入新结点。此栈中的出栈顺序即为先序遍历的序列。

void NicePreOreder(struct BtNode* p)
{
	if (NULL == p)	return;
	std::stack<struct BtNode*> st;
	st.push(p);
	while (!st.empty())
	{
		p = st.top(); st.pop();
		std::cout << p->data << " ";
		if (p->rightchild != NULL)		// 先入右孩子
		{
			st.push(p->rightchild);
		}
		if (p->leftchild != NULL)		// 后入左孩子
		{
			st.push(p->leftchild);
		}

	}
	std::cout << std::endl;
}


非递归后序遍历

对于一个二叉树来说,他需要三部分构成:根、左孩子,右孩子 。而我们仔细观察就会发现对于我们的优先深度遍历来说,不论是哪一种遍历 根结点都会被访问三次

one
two
three
root
A
B
c

并且,针对后序遍历的【左、右、根】模式,我们可以总结出如下规律:

  • 当根结点访问次数为1次时,下一步将访问左孩子。
  • 当根结点访问次数为2次时,下一步将访问右孩子。
  • 当根结点访问次数为3次时,下一步将访问自己。

tips:次方法同样适用于先序遍历和中序遍历。先序遍历在根结点访问次数为1时命中,中序遍历在根结点访问次数为2时命中,后序遍历在根节点访问次数为3时命中。

struct StkNode
{
	struct BtNode* pnode;
	int popnum;		// 结点访问次数
	StkNode(struct BtNode* p = NULL) :pnode(p), popnum(0) {};
};
void StkPastOreder(struct BtNode* p)
{
	if (NULL == p)	return;
	std::stack<StkNode> st;
	st.push(StkNode(p));
	while (!st.empty())
	{
		StkNode node = st.top(); 
		st.pop();    node.popnum++;		// 用出栈次数表示结点访问次数
		if (node.popnum == 3)				// 后序 3 打印根结点
		{
			std::cout << node.pnode->data << " ";
		}
		else 
		{
			st.push(node);
			if (node.popnum == 1 && node.pnode->leftchild != NULL)
			{
				st.push(node.pnode->leftchild);
			}
			else if(node.popnum == 2 && node.pnode->rightchild != NULL)
			{
				st.push(node.pnode->rightchild);
			}
		}

	}
	std::cout << std::endl;
}

先序遍历和中序遍历的写法一样,只需改变对结点引用次数(popnode)的判断条件即可。

代码:略 。。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫RT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值