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