Morris遍历二叉树

通常,我们遍历一颗二叉树都会采用递归的方式,即前序遍历、中序遍历和后序遍历,这三种方法的时间复杂度为O(N),空间复杂度为O(logN);而Morris算法遍历一颗二叉树的时间复杂度为O(2N),空间复杂度为O(1).可以想象这是一件很吸引人的特性。
二叉树是一种非线性的结构,而前面说的三种遍历方法实际上是将非线性转换成线性的过程。即将一个树转变成一个链表的过程。那么除了链表的头和尾外,每个中间点都有一个唯一的前驱和后驱。

Morris算法实施过程中实际上包含了两步,(以中序遍历为例子),第一步,找到当前节点的中序遍历的直接前驱,也就是当前节点的左儿子的右子树的最后一个节点,然后将最后一个节点的右指针指向当前节点。目的是当遍历完左子树后还能回到当前节点。第二步,迭代访问左子树,当访问到左儿子为null时,访问当前节点,下一步访问右儿子。此时右儿子一定不是null,原因在于第一步的时候,实际上已经将右儿子指向了它的中序后继p。而这也表示p的左子树已经遍历完了。此时访问p,然后访问p的右子树。

代码如下:

package com.dacas;

import java.util.LinkedList;
import java.util.List;

/**
 * Created by dave on 2016/6/12.
 */
public class main {
    public static void main(String[] args){
        TreeNode root = generateTreeNode();
        List<TreeNode> list1 = inOrderWithMorris(root);
        System.out.println("inOrderWithMorris:");
        showInfo(list1);
        List<TreeNode> list2 = preOrderWithMoris(root);
        System.out.println("preOrderWithMorris:");
        showInfo(list2);
        List<TreeNode> list3 = inOrder(root);
        System.out.println("inOrder:");
        showInfo(list3);
        List<TreeNode> list4 = preOrder(root);
        System.out.println("preOrder:");
        showInfo(list4);
    }
    private static List<TreeNode> inOrderWithMorris(TreeNode root){
        List<TreeNode> lists = new LinkedList<>();
        TreeNode p = root,tmp;

        while(p != null){
            if(p.left == null){
                lists.add(p);
                p = p.right;
            }else{
                tmp = p.left;
                while(tmp.right != null && tmp.right != p){
                    tmp = tmp.right;
                }
                if(tmp.right == null)//first visit and the left need be visited
                {
                    tmp.right = p;
                    p = p.left;
                }else{//second visit node
                    lists.add(p);
                    tmp.right = null;//restore tree structure
                    p = p.right;//next need to visit right subtree
                }
            }
        }
        return lists;
    }
    private static List<TreeNode> preOrderWithMoris(TreeNode root){
        List<TreeNode> lists = new LinkedList<>();
        TreeNode p = root,tmp;

        while(p != null){
            if(p.left == null){
                lists.add(p);
                p = p.right;
            }else{
                tmp = p.left;
                while(tmp.right != null && tmp.right != p)
                    tmp = tmp.right;
                if(tmp.right == null){//visit root node
                    lists.add(p);
                    tmp.right = p;
                    p = p.left;
                }else{
                    tmp.right = null;
                    p = p.right;
                }
            }
        }
        return lists;
    }
    private static List<TreeNode> inOrder(TreeNode root){
        List<TreeNode> lists = new LinkedList<>();
        inOrderRecurse(lists,root);
        return lists;
    }
    private static void inOrderRecurse(List<TreeNode> lists,TreeNode root){
        if(root == null)
            return;
        inOrderRecurse(lists,root.left);
        lists.add(root);
        inOrderRecurse(lists, root.right);
    }
    private static List<TreeNode> preOrder(TreeNode root){
        List<TreeNode> lists = new LinkedList<>();
        preOrderRecurse(lists, root);
        return lists;
    }
    private static void preOrderRecurse(List<TreeNode> lists,TreeNode root){
        if(root == null)
            return;
        lists.add(root);
        preOrderRecurse(lists, root.left);
        preOrderRecurse(lists,root.right);
    }
    private static void showInfo(List<TreeNode> lists){
        for(TreeNode node:lists){
            System.out.print(node.val+" ");
        }
        System.out.println();
    }
    //创建包含16个节点的
    private static TreeNode generateTreeNode(){
        TreeNode root = new TreeNode(1,new TreeNode(2),new TreeNode(3));
        TreeNode p = root.left;
        p.left = new TreeNode(4,new TreeNode(7),new TreeNode(8));
        p.right = new TreeNode(5,new TreeNode(9),null);

        p = root.right;
        p.left=new TreeNode(6,null,new TreeNode(10));
        return root;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值