先序非递归遍历二叉树解析——面试高频数据结构

一、基本概念

二叉树是笔试面试中高频数据结构。

而二叉树的遍历是解决一切二叉树题目的基础。因此,有必要熟练掌握二叉树的遍历方法,包括递归方法 和 非递归方法。

由于递归方法比较简单,因此,这里我们着重来学习二叉树的非递归遍历方法。


首先明确,二叉树的遍历方法按照访问根节点的次序不同,可以分为如下三种:先序遍历、中序遍历、后序遍历。


先序遍历,即先访问根节点,然后再分别访问左子节点、右子节点。


二、实现策略

实现先序遍历的思路:

1、深度优先法则

深度优先遍历是图的一种遍历算法,二叉树是一种图的特例,因此也可以用深度优先法则来进行遍历。

需要注意的问题是:要考虑节点重复访问的问题!

具体实现方法:利用辅助栈!存储访问的节点

举例说明,比如有树结构如图所示:


按照先序遍历的策略:向左走到头,向右走一步

  1. 访问根节点,并将根节点入栈
  2. 栈不为空,沿栈顶节点的左子树遍历,将途经的所有节点访问并入栈,同时断开父子节点之间的指针;
  3. 若当前栈顶点无左子树,则访问右子树;
  4. 若当前栈顶点无右子树,则将栈顶节点弹出,回到第2步;
  5. 若当前栈顶点有右子树,则将右孩子节点压入栈,并且断开父子之间的指针,回到第2步;
  6. 当栈为空,结束。

实现代码:

#include"iostream"
#include"stack"
using namespace std;

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

class Solution{
public:
	void preOrderTraverse(BiTNode *T)
	{
		if (T == NULL)
			return;
		stack<BiTNode*> assi;//定义辅助栈
		assi.push(T);//压栈
		cout << assi.top()->data;//入栈时候访问

		while (!assi.empty())
		{
			while (assi.top()->lchild)
			{
				cout << assi.top()->lchild->data;
				BiTNode *temp = assi.top();//用于断开父子连接 防止重复访问
				assi.push(assi.top()->lchild);
				temp->lchild = NULL;//断开父子连接
			}
			
			if (!assi.top()->rchild)//若右孩子为空则直接弹出,该节点已经访问输出过了。
				assi.pop();
			else
			{
				cout << assi.top()->rchild->data;
				BiTNode *temp = assi.top();
				assi.push(assi.top()->rchild);
				temp->rchild = NULL;
			}
		}
	}
};


2、利用栈的特性

栈是后进先出,所以可以先访问右子树 再访问左子树,那么在出栈的时候,就是左子树在右子树前面,符合先序遍历的要求。

这种方法的好处是:写代码的时候不用考虑重复访问,断开指针的事情。

具体操作步骤:

  1. 根节点入栈
  2. 栈不为空时,访问栈顶节点并出栈
  3. 若出栈的节点右孩子不为空,右孩子入栈;若出栈节点的左孩子不为空,左孩子入栈
  4. 栈为空时,结束
void preOrderTraverse2(BiTNode *T)
	{
		if (T == NULL)
			return;
		stack<BiTNode *> st;
		st.push(T);
		BiTNode *p = NULL;

		while (!st.empty())
		{
			p = st.top();
			cout << p->data;
			st.pop();

			if (p->rchild != NULL)
				st.push(p->rchild);
			if (p->lchild != NULL)
				st.push(p->lchild);
		}
	}


三、总结

两种思路都借助了栈,思路一只是借助栈临时存储遍历的变量,

思路二,则利用栈的后进先出的特性,来实现先序遍历。

两种思路在编码实现的时候略有区别,需加注意。

总得来说,理解了先序遍历的过程,就可以顺利地写出上面的代码。










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值