二叉树遍历-后序遍历(栈迭代,morris 遍历)

184 阅读1分钟

后序遍历

后序遍历顺序为 左子树-右子树-根结点(左右中)

二叉树节点定义

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    //    TreeNode() {}
    TreeNode(int val) {
        this.val = val;
    }

    TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

栈迭代-修改栈迭代方式的前序遍历

考虑修改栈迭代方式的前序遍历来完成二叉树的后序遍历顺序

前序遍历

public List<Integer> preorder(TreeNode root){
    List<Integer> list = new LinkedList<>();
    Stack<TreeNode>stack = new Stack<>();
    
    while(root!=null || !stack.isEmpty()){
        while(root!=null){
            list.add(root.val);
            stack.push(root);
            root = root.left;
        }
        root = stack.pop();
        root = root.right;
    }
    return list;
}

前序遍历顺序为中左右,可以通过改变遍历顺序为中右左,并每次将输出元素插入到list的第一个元素,即:

public List<Integer> preorder(TreeNode root){
    List<Integer> list = new LinkedList<>();
    Stack<TreeNode>stack = new Stack<>();
    
    while(root!=null || !stack.isEmpty()){
        while(root!=null){
            list.add(0,root.val);
            stack.push(root);
            root = root.right;
        }
        root = stack.pop();
        root = root.left;
    }
    return list;
}

栈迭代后序遍历

使用 pre 指针变量保存上次遍历过的右子树根结点,以此来判断右子树是否遍历过。

public List<Integer> preorder(TreeNode root){
    List<Integer> list = new ArrayList<>();
    Stack<TreeNode>stack = new Stack<>();
    TreeNode pre;
    while(root!=null || !stack.isEmpty()){
        while(root!=null){
            stack.push(root);
            root = root.left;
        }
        root = stack.pop();
        if(root.right==null || root.right==pre){
            list.add(root.val);
            pre = root;
            root = null;
        }else{
            stack.push(root);
            root = root.right;
        }
    }
    return list;
}

morris 后序遍历

public List<Integer> preorder(TreeNode root){
    List<Integer> list = new ArrayList<>();
    root = new TreeNode(-1,root,null);

    TreeNode predecessor;
    while(root!=null){
        if(root.left!=null){
            predecessor = root.left;
            while(predecessor.right!=null&&predecessor.right!=root){
                predecessor = predecessor.right;
            }
            if(predecessor.right==null){
                predecessor.right = root;
                root = root.left;
            }else{
                predecessor = null;
                addnode(root.left,list)
                root = root.right;
            }
        
        }else{
           root = root.right;
        }
    }
    return list;
}

private void addnode(TreeNode root, List<Integer> list) {
    //遍历链表
    TreeNode cur = reverseList(root);
    while (cur != null) {
        list.add(cur.val);
        cur = cur.right;
    }

    reverseList(root);

}

//反转链表
private TreeNode reverseList(TreeNode head) {
    TreeNode cur = head;
    TreeNode pre = null;
    while (cur != null) {
        TreeNode next = cur.right;
        cur.right = pre;
        pre = cur;
        cur = next;
    }
    return pre;
}