Morris Traversal 方法实现前序、中序以及后序遍历二叉树。相比使用栈或者递归(也是经过栈空间)方法,Morris 方法能够在空间复杂度为 O(1)
,时间复杂度为 O(n)
的条件下实现对二叉树的遍历。post
<!--more-->spa
若是当前节点左孩子 cur->left 不为空,那么在当前节点的左子树中找出前驱节点 pre,也就是左子树中最大的点。code
class Solution { public: vector<int> preorderTraversal(TreeNode* root) { TreeNode* cur = root; TreeNode* pre = NULL; vector<int> result; while(cur!=NULL){ if (cur->left == NULL){ result.push_back(cur->val); cur = cur->right; }else{ pre = cur->left; while(pre->right!=NULL && pre->right!=cur){ pre = pre->right; } if (pre->right==NULL){ pre->right=cur; result.push_back(cur->val); cur = cur->left; }else{ pre->right = NULL; cur = cur->right; } } } return result; } };
若是当前节点左孩子 cur->left 不为空,那么在当前节点的左子树中找出前驱节点 pre,也就是左子树中最大的点。递归
class Solution { public: vector<int> inorderTraversal(TreeNode* root) { TreeNode* cur = root; TreeNode* pre = NULL; vector<int> result; while(cur!=NULL){ if (cur->left == NULL){ result.push_back(cur->val); cur = cur->right; }else{ pre = cur->left; while(pre->right!=NULL && pre->right!=cur){ pre = pre->right; } if (pre->right == NULL){ pre->right=cur; cur = cur->left; }else{ pre->right = NULL; result.push_back(cur->val); cur = cur->right; } } } return result; } };
若是当前节点左孩子 cur->left 不为空,那么在当前节点的左子树中找出前驱节点 pre,也就是左子树中最大的点。rem
逆序打印路径其实就是逆序打印单链表节点。先将单链表反转,而后依次打印,接下来从新反转到初始状态。get
class Solution { public: vector<int> postorderTraversal(TreeNode* root) { TreeNode dump(-1); dump.left = root; TreeNode* cur = &dump; TreeNode* pre = NULL; vector<int> result; while(cur!=NULL){ if (cur->left == NULL){ cur = cur->right; }else{ pre = cur->left; while(pre->right!=NULL && pre->right!=cur){ pre = pre->right; } if (pre->right == NULL){ pre->right=cur; cur = cur->left; }else{ printReverse(cur->left, pre, result); pre->right = NULL; cur = cur->right; } } } return result; } void printReverse(TreeNode* from, TreeNode* to, vector<int>& result){ Reverse(from, to); TreeNode* p = to; while(true){ result.push_back(p->val); if(p == from){ break; } p = p->right; } Reverse(to, from); } void Reverse(TreeNode* from, TreeNode* to){ TreeNode* x = from; TreeNode* y = from->right; TreeNode* z; if (from == to){ return; } x->right = NULL; while(x != to){ z = y->right; y->right = x; x = y; y = z; } } };
Morris 方法遍历之因此可以在 O(1)
的空间的条件下完成是由于它充分利用到叶子的左右孩子来记录上层关系,从而不须要额外的栈空间来记录顺序关系。经过三种遍历能够看到,其实整体上的代码逻辑没有发生改变,主要是改变了输出结果的时机和方式。it