二叉树的非递归遍历-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 阅读(255) 评论(0) 收藏 举报
浙公网安备 33010602011771号