二叉树3——二叉树的统一迭代法

此时我们在二叉树:一入递归深似海,从此offer是路人 (opens new window)中用递归的方式,实现了二叉树前中后序的遍历。

在二叉树:听说递归能做的,栈也能做! (opens new window)中用栈实现了二叉树前后中序的迭代遍历(非递归)。

之后我们发现迭代法实现的先中后序,其实风格也不是那么统一,除了先序和后序,有关联,中序完全就是另一个风格了,一会用栈遍历,一会又用指针来遍历。

实践过的同学,也会发现使用迭代法实现先中后序遍历,很难写出统一的代码,不像是递归法,实现了其中的一种遍历方式,其他两种只要稍稍改一下节点顺序就可以了。

其实针对三种遍历方式,使用迭代法是可以写出统一风格的代码!

重头戏来了,接下来介绍一下统一写法。

我们以中序遍历为例,在二叉树:听说递归能做的,栈也能做! (opens new window)中提到说使用栈的话,无法同时解决访问节点(遍历节点)和处理节点(将元素放进结果集)不一致的情况。

那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。

如何标记呢,就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。 这种方法也可以叫做标记法。

迭代法中序遍历

中序遍历代码如下:

class Solution{
public:
	vector<int> inorderTraversal(TreeNode* root){
		vector<int> result;
		stack<TreeNode*> st;
		if (root != NULL) st.push(root);
		while (!st.empty()){
			TreeNode* node = st.pop();
			if (node != NULL) {
				st.pop();	//将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
				if (node->right) st.push(node->right);	//添加右节点(空节点不入栈)
				st.push(node);					//添加中节点
				st.push(NULL);				// 中节点访问过,但是还没有处理,加入空节点作为标记
				if (node->left) st.push(node->left);	//添加左节点(空节点不入栈)
			} else{ // 只有遇到空节点的时候,才将下一个节点放进结果集
			st.pop();				//将空节点弹出
			node = st.pop();		//重新取出栈中元素
			st.pop();
			result.push_back(node->val);	// 加入到结果集
		}
	}
	return result;
	}
};

在这里插入图片描述

动画中,result数组就是最终结果集。

可以看出我们将访问的节点直接加入到栈中,但如果是处理的节点则后面放入一个空节点, 这样只有空节点弹出的时候,才将下一个节点放进结果集。

此时我们再来看前序遍历代码。

迭代法前序遍历

迭代法前序遍历代码如下: (注意此时我们和中序遍历相比仅仅改变了两行代码的顺序)

class Solution
public:
	vector<int> preorderTraversal(TreeNode* root){
		vector<int> result;
		stack<TreeNode*> st;
		if (root != NULL) st.push(root);
		while (!st.empty()){
			TreeNode* node = st.top();
			if (node != NULL) {
				st.pop;
				if (node->right) st.push(node->right);
				if (node->left) st.push(node->left);
				st.push(node);
				st.push(NULL);
			}else {
				st.pop();
				node = st.pop();
				st.pop();
				result.push_back(node->val);
				}
			}
			return result;
		}
	};

迭代法后序遍历

后续遍历代码如下: (注意此时我们和中序遍历相比仅仅改变了两行代码的顺序)

class Solution
public:
	vector<int> postorderTraversal(TreeNode*  root) {
		vector<int> result;
		stack<TreeNode*> st;
		if (root != NULL) st.push(root);
		while(!st.empty()){
			TreeNode* node = st.top();
			if (node != NULL){
				st.pop();
				st.push(node);
				st.push(NULL);

				if (node->right) st.push(node->right);
				if (node->left) st.push(node->left);
}
else{
	st.pop();
	node = st.top();
	st.pop();
	result.push_back(node->val);
}
}
return resutl;
}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

joker-wt

我的心愿是——世界和平

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

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

打赏作者

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

抵扣说明:

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

余额充值