Morris 二叉树遍历

Morris 二叉树遍历

对于二叉树遍历有很多的方法,先序遍历,中序遍历,后序遍历,层次遍历等等。但是这些遍历方法每个节点至少访问一次并且需要记录上一次访问的节点。因此时间复杂度为O(n),空间复杂度为O(n)或O(log(n))。下面介绍的Morris 二叉树遍历方法 时间复杂度为O(n),空间复杂度为O(1)。

Morris遍历优点是空间复杂度为O(1),并且遍历完后不改变树的结构。缺点是时间会增长,因为大部分节点会访问两次。这是典型的时间换取空间的例子。这个算法空间复杂度能做到O(1)精妙之处在于它利用叶子节点的左右指针指向该叶子节点在某种遍历顺序下的前驱节点或后继节点。下面以中序遍历为例,介绍Morris算法。

算法步骤

  1. 如果当前节点的左孩子为空,输出当前节点,并将当前节点的右孩子设置为当前节点。
  2. 如果当前节点的左孩子不为空,则在当前节点的左子树上寻找当前节点在中序遍历下的前驱节点。
    a) 如果当前节点的前驱节点的右孩子为空,则将前驱节点的右孩子指向当前节点。将当前节点的左孩子设置为当前节点。
    b) 如果当前节点的前驱节点的右孩子指向当前节点,则将前驱节点的右孩子设置为NULL(恢复树的结构),输出当前节点,并将当前节点的右孩子设置为当前节点。

图示过程如下:

这里写图片描述

算法流程图

Created with Raphaël 2.1.0 cur = root cur == null End cur.left == null print cur.val cur = cur.right find prev prev.right == null prev.right = cur cur = cur.left pre.right = null yes no yes no yes no

java 代码

 public void MorrisTraverse(TreeNode root) {
        TreeNode cur = root;
        TreeNode prev = null;
        while(cur != null){
            if(cur.left == null){
                System.out.prinln(cur.val);
                cur = cur.right;
            }
            else{
                prev = cur.left;
                while(prev.right != null && prev.right != cur){
                    prev = prev.right;
                }
                if(prev.right == null){
                    prev.right = cur;
                    cur = cur.left;
                }
                else{
                    System.out.println(cur.val);
                    prev.right = null;
                    cur = cur.right;
                }
            }
        }
    }

参考资料:
http://www.cnblogs.com/AnnieKim/archive/2013/06/15/MorrisTraversal.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值