一、需求
给你一棵二叉树的根节点 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
- 加强了对算法的分析能力