二叉树的非递归遍历-O(1)空间

 问题描述:

 对一颗二叉树进行中序遍历,要求空间复杂度为O(1),即常数空间。

解题方法:

  由于要求空间复杂度为O(1),显然不能采用递归和栈的方式来遍历。由于树中的叶子节点的左右指针域都为空,

因此可以利用叶子节点的指针域记录后驱节点,类似于线索二叉树,这种方法叫Morris Traversal方法。在Morris方法

中不需要为每个节点额外分配指针指向其前驱(predecessor)和后继节点(successor),只需要利用叶子节点中的

左右空指针指向某种顺序遍历下的前驱节点或后继节点就可以了。

算法流程:

以中序遍历为例,设置两个指针变量,pre,cur.,其中pre为前驱节点,cur为当前节点。初始时cur指向根节点。

1. 如果当前节点的左孩子为空,则输出当前节点并将其右孩子作为当前节点。

2. 如果当前节点的左孩子不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点。

   a) 如果前驱节点的右孩子为空,将它的右孩子设置为当前节点。当前节点更新为当前节点的左孩子。

   b) 如果前驱节点的右孩子为当前节点,将它的右孩子重新设为空(恢复树的形状)。输出当前节点。当前节点更新为当前节点的右孩子。

3. 重复以上1、2直到当前节点为空。

struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
	vector<TreeNode*> Morris_InOrder(TreeNode* root) {
		vector<TreeNode*> res;
		TreeNode *cur = NULL, *pre = NULL;
		cur = root;
		while (cur)
		{
			if (cur->left == NULL)
			{
				res.push_back(cur);
				cur = cur->right;
			}
			else {
				pre = cur->left;
				while (pre->right && pre->right != cur) pre = pre->right;
				if (pre->right == NULL)
				{
					pre->right = cur;
					cur = cur->left;
				}
				else {
					pre->right = NULL;
					res.push_back(cur);
					cur = cur->right;
				}
			}
		}
		return res;
	}
};

  

posted on 2018-02-06 11:28  IT_Amateur  阅读(237)  评论(0编辑  收藏  举报

导航