二叉树的非递归遍历-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) 编辑 收藏 举报