文章链接:代码随想录递归遍历 代码随想录迭代遍历 代码随想录统一迭代法
视频链接:代码随想录递归遍历 代码随想录迭代遍历前序后序 代码随想录迭代遍历中序
目录
代码随想录算法训练营第十三天 | LeetCode 144. 二叉树的前序遍历、LeetCode 145. 二叉树的后序遍历、LeetCode 94. 二叉树的中序遍历
1. 二叉树理论基础
1.1 树型结构概念
1.2 概念
1.3 树的表示形式
1.4 二叉树概念
1.5 两种特殊的二叉树
1.6 二叉树的性质
1.7 二叉树的存储
1.8 二叉树的遍历
1.8.1 前中后序遍历
1.8.2 层序遍历
2. 二叉树遍历
2.1 递归思路(完成下面下个问题,可以养成一个好的递归思路)
2.2 代码
3. LeetCode 144. 二叉树的前序遍历
3.1 非递归思路
3.2 代码
4. LeetCode 145. 二叉树的后序遍历
4.1 非递归思路
4.2 代码
5. LeetCode 94. 二叉树的中序遍历
5.1 非递归思路
5.2 代码
将这棵二叉树存入数组中相应的下标对应其同样的位置,如下图所示:
而二叉树的链式存储是通过一个一个的节点引用起来的,结构示意图如下:
// 前序遍历·递归·LC144_二叉树的前序遍历
class Solution {
public List preorderTraversal(TreeNode root) {
List result = new ArrayList();
preorder(root, result);
return result;
}
public void preorder(TreeNode root, List result) {
if (root == null) {
return;
}
result.add(root.val);
preorder(root.left, result);
preorder(root.right, result);
}
}
// 中序遍历·递归·LC94_二叉树的中序遍历
class Solution {
public List inorderTraversal(TreeNode root) {
List res = new ArrayList<>();
inorder(root, res);
return res;
}
void inorder(TreeNode root, List list) {
if (root == null) {
return;
}
inorder(root.left, list);
list.add(root.val); // 注意这一句
inorder(root.right, list);
}
}
// 后序遍历·递归·LC145_二叉树的后序遍历
class Solution {
public List postorderTraversal(TreeNode root) {
List res = new ArrayList<>();
postorder(root, res);
return res;
}
void postorder(TreeNode root, List list) {
if (root == null) {
return;
}
postorder(root.left, list);
postorder(root.right, list);
list.add(root.val); // 注意这一句
}
}
// 前序遍历顺序:中-左-右,入栈顺序:中-右-左
class Solution {
public List preorderTraversal(TreeNode root) {
List result = new ArrayList<>();
if (root == null){
return result;
}
Stack stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);
if (node.right != null){
stack.push(node.right);
}
if (node.left != null){
stack.push(node.left);
}
}
return result;
}
}
// 后序遍历顺序 左-右-中 入栈顺序:中-左-右 出栈顺序:中-右-左, 最后翻转结果
class Solution {
public List postorderTraversal(TreeNode root) {
List result = new ArrayList<>();
if (root == null){
return result;
}
Stack stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);
if (node.left != null){
stack.push(node.left);
}
if (node.right != null){
stack.push(node.right);
}
}
Collections.reverse(result);
return result;
}
}
1. 由于中序遍历的特殊性无法在以上的代码作更改而实现,因此需要别的实现方法
2. 我们处理二叉树时有两步关键:访问节点和处理节点
3. 由于我们的顺序是“左根右”,而我们先访问到的一定是根节点,因此我们设置一个指针,访问到的节点都先入栈,当我们遇到左孩子为空时就弹出该节点,右孩子为空时说明是叶子节点,就弹出该节点的父节点
4. 我们的循环终止条件就是指针和栈同时为空时就结束循环
5. 我们的终止是一路向左,左为空就先从栈里弹出一个元素,再到这个元素的右孩子,再一路向左,循环往复
// 中序遍历顺序: 左-中-右 入栈顺序: 左-右
class Solution {
public List inorderTraversal(TreeNode root) {
List result = new ArrayList<>();
if (root == null){
return result;
}
Stack stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()){
if (cur != null){
stack.push(cur);
cur = cur.left;
}else{
cur = stack.pop();
result.add(cur.val);
cur = cur.right;
}
}
return result;
}
}