标签:turn fmb 栈空间 traversal 复杂度 状态 pre 左右 遍历
Morris Traversal 方法实现前序、中序以及后序遍历二叉树。相比使用栈或者递归(也是通过栈空间)方法,Morris 方法可以在空间复杂度为 O(1)
,时间复杂度为 O(n)
的条件下实现对二叉树的遍历。
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;
}
};
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;
}
};
逆序打印路径其实就是逆序打印单链表节点。先将单链表反转,然后依次打印,接下来重新反转到初始状态。
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)
的空间的条件下完成是因为它充分利用到叶子的左右孩子来记录上层关系,从而不需要额外的栈空间来记录顺序关系。通过三种遍历可以看到,其实总体上的代码逻辑没有发生改变,主要是改变了输出结果的时机和方式。
https://www.ouyangsong.com/posts/27490/
标签:turn fmb 栈空间 traversal 复杂度 状态 pre 左右 遍历
原文地址:https://www.cnblogs.com/ouyangsong/p/9348179.html