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二叉树遍历算法

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

Morris方法遍历二叉树

本文主要解决一个问题,如何实现二叉树的前中后序遍历,有两个要求: O(1)空间复杂度,即只能使用常数空间; 二叉树的形状不能被破坏(中间过程允许改变其形状)。 通常,实现二叉树的前序(preorder...
  • zhaoyunfullmetal
  • zhaoyunfullmetal
  • 2015年08月29日 16:27
  • 1797

Morris算法进行二叉树遍历

二叉树作为计算机中的一个重要数据结构,在很多领域都会涉及到,而提到二叉树,我们首先想到的就是其3种遍历方式--前序、中序和后序,对于这3种遍历方式,我们很容易通过使用递归或者迭代(http://blo...
  • yangfeisc
  • yangfeisc
  • 2015年05月12日 19:45
  • 1221

二叉树神级遍历算法——Morris遍历(C++版)

题目: 设计一个算法实现二叉树的三种遍历(前序遍历 中序遍历 后序遍历)。 要求时间复杂度为O(n) 空间复杂度为O(1)。   思路: 空间复杂度O(1)的要求很严格。常规的递归实现是显然不能满足要...
  • u013575812
  • u013575812
  • 2015年11月27日 14:36
  • 2424

bst三种遍历及其他

#include #include //using stack; using namespace std; struct Node { int data; Node *left; Node...
  • fall221
  • fall221
  • 2013年09月10日 13:53
  • 1188

LeetCode 314. Binary Tree Vertical Order Traversal(二叉树垂直遍历)

原题网址:https://leetcode.com/problems/binary-tree-vertical-order-traversal/ Given a binary tree, retu...
  • jmspan
  • jmspan
  • 2016年04月22日 02:19
  • 2870

克努斯-莫里斯-普拉特算法(Knuth–Morris–Pratt algorithm) c简单实现

偶尔看到的大名鼎鼎的KMP算法。 wiki在此int kmp_search(char *needle, char *haystack) { if(NULL==haystack || NULL...
  • baidu_27677097
  • baidu_27677097
  • 2015年05月08日 18:43
  • 629

Binary Tree Preorder Traversal -- LeetCode

原题链接: http://oj.leetcode.com/problems/binary-tree-preorder-traversal/  跟Binary Tree Inorder Travers...
  • linhuanmars
  • linhuanmars
  • 2014年03月18日 03:33
  • 12897

算法练习笔记(七)——在BST树中的遍历

一般来说,BST(二叉排序树)有分三种遍历,前序遍历,中序遍历和后序遍历。 前序遍历顺序是根在前的根,左子树,右子树(也是我们一般来表示一棵树的方法) 中序:左子树,根,右子树  后序:左子树,...
  • d921737171
  • d921737171
  • 2017年03月31日 12:47
  • 211

Morris神级遍历二叉树,时间复杂度为O(1)

Morris算法介绍Morris算法在遍历的时候避免使用了栈结构,而是让下层到上层有指针,具体是通过底层节点指向NULL的空闲指针返回上层的某个节点,从而完成下层到上层的移动。我们知道二叉树有很多空闲...
  • wy1550365215
  • wy1550365215
  • 2017年08月22日 14:44
  • 310
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Morris Traversal算法遍历BST c实现
举报原因:
原因补充:

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