Morris Traversal算法遍历BST c实现

原创 2015年07月07日 17:42:34

Morris Traversal本来是一种中续遍历的经典算法,相对于递归与使用椎的遍历。不需要额外的空间,也就是说空间复杂度为O(1)。
leetcode 中关于二叉树3种遍历方式的题,其中要求不能用递归。那么Morris就是一种可取的方案。
以下都是leetcode oj接受了的解。

经典中续

int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    int buff[255];
    *returnSize=0;
    struct TreeNode *cur=root;
    struct TreeNode *prev=NULL;
    while(cur){
        if(cur->left){
            prev=cur->left;
            while(prev->right && prev->right!=cur)
                prev=prev->right;

            if(prev->right){
                // just come from precessor
                prev->right=NULL;
                buff[*returnSize]=cur->val;
                ++(*returnSize);
                cur=cur->right;
            }else{
                prev->right=cur;
                cur=cur->left;
            }

        }else{
            buff[*returnSize]=cur->val;
            ++(*returnSize);
            cur=cur->right;
        }
    }
    int bs=sizeof(int)*(*returnSize);
    int *res=malloc(bs);

    memcpy(res,buff,bs);
    return res;
}

算法的关键在于使用当前结点左结点的最右结点的空指针,指回当前结点用于遍历的时候回退。事实上这个结点正好是当前结点的中续遍历的前驱结点。


稍微修改就得到了先续遍历

int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    int buff[255];
    *returnSize=0;
    struct TreeNode *cur=root;
    struct TreeNode *prev=NULL;
    while(cur){
        if(cur->left){
            prev=cur->left;
            while(prev->right && prev->right!=cur)
                prev=prev->right;

            if(prev->right){
                // just come from precessor
                prev->right=NULL;
                cur=cur->right;
            }else{
                prev->right=cur;
                buff[*returnSize]=cur->val;
                ++(*returnSize);
                cur=cur->left;
            }

        }else{
            buff[*returnSize]=cur->val;
            ++(*returnSize);
            cur=cur->right;
        }
    }
    int bs=sizeof(int)*(*returnSize);
    int *res=malloc(bs);

    memcpy(res,buff,bs);
    return res;
}

后续的情况更加复杂一些。主要的区别是要逆向输出当前结点左结点的右子树。所以root结点需要一个额外的结点来辅助完成遍历。

int* postorderTraversal(struct TreeNode* root, int* returnSize) {
    int buff[255];
    *returnSize=0;
    struct TreeNode dump;
    dump.left=root;
    dump.right=NULL;
    dump.val=0;
    struct TreeNode *cur=&dump;
    struct TreeNode *prev=NULL;
    while(cur){
        if(cur->left){
            prev=cur->left;
            while(prev->right && prev->right!=cur)
                prev=prev->right;

            if(prev->right){
                // just come from precessor
                struct TreeNode *p=cur->left;
                int rn=0;
                while(p!=cur){
                    buff[*returnSize]=p->val;
                    ++(*returnSize);
                    p=p->right;
                    ++rn;
                }
                //reverse right branch vals
                int pt=*returnSize -1;
                int ph=(*returnSize -rn);
                while(pt>ph){
                    int tmp=buff[ph];
                    buff[ph]=buff[pt];
                    buff[pt]=tmp;
                    --pt;
                    ++ph;
                }
                prev->right=NULL;
                cur=cur->right;
            }else{
                prev->right=cur;
                cur=cur->left;
            }

        }else{
            cur=cur->right;
        }
    }
    int bs=sizeof(int)*(*returnSize);
    int *res=malloc(bs);

    memcpy(res,buff,bs);
    return res;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

数据结构与算法学习笔记——二叉树遍历(二)(Morris Traversal)

前面介绍了一般的二叉树遍历方法,包括递归和迭代。这两种方法的空间复杂度都是O(n)。 二叉树遍历的另外一种方法:Morris遍历二叉树 的空间复杂度为O(1),并且还不改变原本的树结构,时间复杂度依...

leetcode99---Recover Binary Search Tree(morris中序遍历恢复BST)

问题描述: Two elements of a binary search tree (BST) are swapped by mistake.Recover the tree without ch...
  • will130
  • will130
  • 2015年12月28日 11:06
  • 235

二叉树遍历之morris traversal

刚开始接触到这个是因为算法导论习题10.4-5,其中有一句话说不能改变二叉树结构,即使临时改变也不行,个人就感觉改变二叉树结构也可以进行遍历。 搜索的过程中发现了morris 遍历,刚开始根...
  • wdq347
  • wdq347
  • 2013年04月26日 11:40
  • 5360

【算法】二叉树的非递归遍历的简洁写法/迭代器实现/O(1)空间复杂度的Morris遍历

事情的起因是这样的,一大早突然想到C++的STL里set是由红黑树实现的,那set遍历的时候iterator是怎么实现的呢,自己想了个不算太好的算法,于是就想着去网上找找,看到一个人说就是把二叉树的非...

精妙的Morris二叉树遍历算法

今天介绍一种精妙的无堆栈,O(1)空间的二叉树遍历算法:Morris遍历,它是Morris发明的。 大家都很熟悉用递归和堆栈来实现二叉树的遍历,比如,前序遍历,中序遍历,后序遍历。但Morri...

Morris二叉树遍历算法

在遍历儿叉树时,常常使用的是递归遍历,或者是借助于栈来迭代,在遍历过程中,每个节点仅访问一次,所以这样遍历的时间复杂度为O(n),空间复杂度为O(n),并且递归的算法易于理解和实现,二叉树的递归遍历算...

【LeetCode-面试算法经典-Java实现】【094-Binary Tree Inorder Traversal(二叉树中序遍历)】

【094-Binary Tree Inorder Traversal(二叉树中序遍历)】【LeetCode-面试算法经典-Java实现】【所有题目目录索引】原题  Given a binary tre...

【LeetCode-面试算法经典-Java实现】【107-Binary Tree Level Order Traversal II(二叉树层序遍历II)】

【107-Binary Tree Level Order Traversal II(二叉树层序遍历II)】【LeetCode-面试算法经典-Java实现】【所有题目目录索引】原题  Given a b...

【LeetCode-面试算法经典-Java实现】【103-Binary Tree Zigzag Level Order Traversal(二叉树分层Z字形遍历)】

【103-Binary Tree Zigzag Level Order Traversal(二叉树分层Z字形遍历)】【LeetCode-面试算法经典-Java实现】【所有题目目录索引】原题  Give...

【LeetCode-面试算法经典-Java实现】【102-Binary Tree Level Order Traversal(二叉树层序遍历)】

【102-Binary Tree Level Order Traversal(二叉树层序遍历)】【LeetCode-面试算法经典-Java实现】【所有题目目录索引】原题  Given a binary...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Morris Traversal算法遍历BST c实现
举报原因:
原因补充:

(最多只允许输入30个字)