更好的中序遍历-Morris中序遍历(java实现)

二叉树的中序遍历

二叉树的中序遍历,遍历顺序是先从左子树开始,接下访问根节点,然后访问右子树,我自己为了方便记忆,就是想中序,就是下一个访问中间节点,也就是从左子树开始,接下来访问根节点。

一般中序遍历是递归或者非递归方式实现。非递归是用栈实现。递归有递归深度,栈也有栈空间,这两种方式的空间复杂度都是O(n)。

递归实现的中序遍历:

1   public static void InOrder(TreeNode root) {
2        if (root == null) return;
3        InOrder(root.left);
4        System.out.println(root.val);
5        InOrder(root.right);
6    }

非递归实现的中序遍历:

 1   public static void InOrderByStack(TreeNode root) {
 2        if (root == null) return;
 3        Stack<TreeNode> stack = new Stack<>();
 4        while (!stack.isEmpty() || root != null) {
 5            while (root != null) {
 6                stack.push(root);
 7                root = root.left;
 8            }
 9            root = stack.pop();
10            System.out.println(root.val);
11            root = root.right;
12        }
13    }

更好的空间复杂度

因为中序遍历时候,每访问一个节点,不知道下一个节点是哪个,所以借助于递归和栈实现,导致空间复杂度是O(n),而Morris中序遍历是,先去找节点的过程就已经把每个节点的下一个节点已经找到,做了牵线,所以依次遍历即可。
具体就是修改节点的right指针,使之指向下一个节点。如下图所示:
在这里插入图片描述
修改1节点的right指针指向4,修改6节点指针指向节点9.

算法步骤

1、如果当前节点cur左子树是空的,那么访问此节点就可以,继续到右子树中去访问,

2、如果当前左子树不是空的,说明当前结点的前驱节点就在左子树中,就去左子树找。就可以在左子树中一直往右走,走到低就是当前节点的前驱。设置为pre。

如果pre的右子树是空的,修改pre的right指针即可,指向cur。

如果pre的右子树非空,说明已经被修改过。那么访问此节点即可,并把它的right改回来为null,然后继续在cur的右子树中找。

 1    public static void MorrisInOrder(TreeNode root) {
 2        TreeNode cur = root;
 3        TreeNode pre;
 4        while (cur != null) {
 5            //左子树为空
 6            if (cur.left == null) {
 7                System.out.println(cur.val);
 8                cur = cur.right;
 9                continue;
10            }
11            //找它的前面节点
12            pre = cur.left;
13            while (pre.right != null && pre.right != cur) {
14                pre = pre.right;
15            }
16            //找到后就要修改right指针
17            if (pre.right == null) {
18                pre.right = cur;
19                //找下一个cur的前继
20                cur = cur.left;
21            } else {  //之前就修改过了,继续找cur的后继
22                pre.right = null;
23                System.out.println(cur.val);
24                cur = cur.right;
25            }
26        }
27    }

Morris中序遍历时间复杂度是O(n),空间复杂度是O(1)。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值