算法34:二叉树的后序遍历

一、需求

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历

示例 1:

在这里插入图片描述

输入:root = [1,null,2,3]
输出:[3,2,1]

示例 2:

输入:root = []
输出:[]

示例 3:

在这里插入图片描述

输入:root = [1]
输出:[1]

提示:

  • 树中节点的数目在范围 [0, 100]
  • -100 <= Node.val <= 100

**进阶:**递归算法很简单,你可以通过迭代算法完成吗?

二、思路分析图

迭代逻辑

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

三、代码

(一)公共代码(树节点类)

package com.bessky.pss.wzw.SuanFa;

import java.util.ArrayList;
import java.util.List;

/**
 * 树节点类
 *
 * @author 王子威
 * @date 2022/7/27
 */
public 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;
    }

    /**
     * 遍历显示
     *
     * @return
     */
    public String display()
    {
        // 创建存储先序遍历后的结果
        List<Integer> results = new ArrayList<>();

        // 调用:递归方法
        this.inorder(this, results);

        return results.toString();
    }

    /**
     * 递归方法体
     *
     * @param root
     * @param results
     */
    public void inorder(TreeNode root, List<Integer> results)
    {
        if (root == null)
        {

            return;
        }

        // 调用:当最左时就存储 || 或左没有时存储
        results.add(root.val);
        // 调用:递归方法(先把最左边的拿到)
        inorder(root.left, results);

        // 调用:递归方法(左没有时就递归右边)
        inorder(root.right, results);
    }
}

(二)数据初始化

/**
 * 入口
 *      145、二叉树的后序遍历
 * 输入:
 *      [1,null,2,3]
 * 输出:
 *      [3,2,1]
 * 解释:
 *      1.递归方案
 *      2.迭代方案
 *      3.Morris方案
 */
@Test
public void suanfa34()
{
    // 初始化
    TreeNode root = new TreeNode(1, null, new TreeNode(2, new TreeNode(3), null));

    // 打印
    List<Integer> result1 = new ArrayList<>();
    this.recursionPostorderTraversal(root, result1);
    System.out.println("递归方案 = " + result1.toString());

    List<Integer> result2 = new ArrayList<>();
    this.iterationPostorderTraversal(root, result2);
    System.out.println("迭代方案 = " + result2.toString());

    List<Integer> result3 = new ArrayList<>();
    this.morrisPostorderTraversal(root, result3);
    System.out.println("Morris方案 = " + result3.toString());
}

(三)递归方案

/**
 * 递归方案
 *
 * @param root
 * @param result
 */
private void recursionPostorderTraversal(TreeNode root, List<Integer> result)
{
    if (root == null)
    {
        return;
    }

    this.recursionPostorderTraversal(root.left, result);
    this.recursionPostorderTraversal(root.right, result);
    result.add(root.val);
}

(四)迭代方案

/**
 * 迭代方案
 *
 * @param root
 * @param result
 */
private void iterationPostorderTraversal(TreeNode root, List<Integer> result)
{
    if (root == null)
    {
        return;
    }

    TreeNode temp = root;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    while (!stack.isEmpty())
    {
        TreeNode peek = stack.peek();
        if (peek.left != null && peek.left != temp && peek.right != temp)
        {
            stack.push(peek.left);
        }
        else if (peek.right != null && peek.right != temp)
        {
            stack.push(peek.right);
        }
        else
        {
            temp = peek;
            result.add(stack.pop().val);
        }
    }
}

(五)Morris方案

/**
 * Morris方案
 *
 * @param root
 * @param result
 */
private void morrisPostorderTraversal(TreeNode root, List<Integer> result)
{
    if (root == null)
    {
        return;
    }

    TreeNode p1 = root, p2;

    while (p1 != null)
    {
        p2 = p1.left;
        if (p2 != null)
        {
            while (p2.right != null && p2.right != p1)
            {
                p2 = p2.right;
            }
            if (p2.right == null)
            {
                p2.right = p1;
                p1 = p1.left;
                continue;
            }
            else
            {
                p2.right = null;
                addResult(result, p1.left);
            }
        }
        p1 = p1.right;
    }
    addResult(result, root);
}

addResult

/**
 * 添加结果
 *
 * @param result
 * @param node
 */
public void addResult(List<Integer> result, TreeNode node)
{
    int count = 0;
    while (node != null)
    {
        ++count;
        result.add(node.val);
        node = node.right;
    }
    int left = result.size() - count, right = result.size() - 1;
    while (left < right)
    {
        int temp = result.get(left);
        result.set(left, result.get(right));
        result.set(right, temp);
        left++;
        right--;
    }
}

(六)结果图

在这里插入图片描述

作者:王子威

四、总结

  • 学习了二叉树的后序遍历
  • 递归方案技巧:前序遍历(添加放前面),中序遍历(添加放中间),后序遍历(添加放后面)
  • Morris好萌,理解的不透彻
  • 迭代使用Stack堆的特性,循环翻倍
  • Stack堆,先进先出,和队列是同样的,所以这里队列也可以做
  • 算法兴趣+1 总:34
  • 加强了对算法的分析能力
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值