今天在切leetcode的时候看到一个Morris算法,用来中序遍历二叉树,非递归,O(1)空间。觉得很强大。记录一下。

基本思想是利用了Threaded Binary Tree

步骤如下:

  1. current节点设置为root。如果current不为空,到2,否则返回;
  2. 如果current没有左子树,输出current的值,current等于current.right;
  3. 如果current有左子树,首先找到current节点的precedent,也就是该节点左子树中最最右边那个节点。然后把最最右边这个节点的右link指向当前节点。如下图。

Morris InOrder Traverse Binary Tree 无需使用递归和栈

    e.g. 当current是7的时候,我们找到4,并人为地添加一个link到current(绿色的link)。

    current等于current.left;回到2.

有同学说,如果遍历到结点4,按照算法(4没有左子树),不是就又回到了7么,然后循环怎么结束呢?假设如果通过4回到了7,再找寻找7的precendent的过程中,我们会发现环,7->3->4->7(7的左子树中最最右边的节点是自己),那么我们知道7的左子树已经遍历完成,输出7,然后继续遍历7的右子树。

我们的代码如下:

首先假设有一个TreeNode数据结构是这样的。

1 public class TreeNode {
2      int val;
3      TreeNode left;
4      TreeNode right;
5      TreeNode(int x) { val = x; }
6 }

然后是遍历:

public ArrayList<Integer> inorderMorrisTraversal(TreeNode root){
        sequence = new ArrayList<Integer>();
        TreeNode current = root;
        TreeNode pre = null;
        while(current != null){
            if(current.left == null){
                sequence.add(current.val);
                current = current.right;
            }else {
                pre = current.left;
                //找到当前节点的前任,也就是它左子树的最右节点
                while(pre.right != null && pre.right != current){
                    pre = pre.right;
                }
                if(pre.right == null){//我们遇到的左子树
                    pre.right = current;
                    current = current.left;
                }else {//说明pre.right == current,构成了一个环,说明之前已经遍历过了current的左子树,可以输出current了。
                    pre.right = null;
                    sequence.add(current.val);
                    current = current.right;
                }
            }
        }
        return sequence;
View Code

相关文章:

  • 2021-06-18
  • 2022-12-23
  • 2021-12-02
猜你喜欢
  • 2021-07-28
  • 2021-12-11
  • 2022-01-09
  • 2021-08-18
  • 2021-06-16
相关资源
相似解决方案