面试经典算法系列之二叉树7 -- 二叉树的中序遍历

面试经典算法22 - 二叉树的中序遍历

LeetCode.94
公众号:阿Q技术站

问题描述

给定一个二叉树的根节点 root ,返回 它的 中序 遍历

示例 1:

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

示例 2:

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

示例 3:

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

提示:

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

思路

递归
  1. 如果根节点为空,返回空数组。
  2. 对根节点的左子树进行递归中序遍历,将结果存入结果数组。
  3. 将根节点的值存入结果数组。
  4. 对根节点的右子树进行递归中序遍历,将结果存入结果数组。
  5. 返回结果数组。
迭代
  1. 创建一个空数组 result 用于存储遍历结果。
  2. 创建一个辅助栈 st 用于存储遍历过程中的节点。
  3. 如果根节点为空,直接返回空数组。
  4. 从根节点开始,依次将左子节点入栈,直到左子节点为空。
  5. 弹出栈顶节点,将节点值加入结果数组,并将当前节点指向右子节点。
  6. 重复步骤 2 和步骤 3,直到栈为空且当前节点为空。

图解

这里还是给大家使用迭代法做一个图解。

  1. 先将头结点插入栈中。

image-20240229223447080

  1. 左节点不为空时,将左节点插入栈中,直至左节点遍历完。

image-20240229225012083

  1. 弹出栈顶元素,并添加至结果集。

image-20240229231315751

  1. 将根节点的右子节点添加进栈中。

image-20240229232732118

  1. 将右子节点的左子节点添加进栈中

image-20240229232902185

  1. 当前根节点(右子节点)的左子节点遍历完成,取出栈顶元素,并添加进结果集。

image-20240229233049675

  1. 继续将右子节点添加进栈中,直至遍历完。

image-20240229233211861

  1. 弹出栈顶元素,并添加进结果集。

image-20240229233306449

参考代码

C++
递归
#include <iostream>
#include <vector>

using namespace std;

// 二叉树节点的定义
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

// 递归中序遍历
void inorderTraversal(TreeNode* root, vector<int>& result) {
    if (root == nullptr) {
        return; // 如果节点为空,直接返回
    }
    inorderTraversal(root->left, result); // 递归遍历左子树
    result.push_back(root->val); // 将根节点的值加入结果数组
    inorderTraversal(root->right, result); // 递归遍历右子树
}

// 创建二叉树
TreeNode* createTree(vector<int>& nodes, int index) {
    if (index >= nodes.size() || nodes[index] == -1) {
        return nullptr; // 如果节点为空,则返回nullptr
    }
    TreeNode* root = new TreeNode(nodes[index]); // 创建当前节点
    root->left = createTree(nodes, 2 * index + 1); // 创建左子树
    root->right = createTree(nodes, 2 * index + 2); // 创建右子树
    return root; // 返回当前节点
}

// 销毁二叉树
void destroyTree(TreeNode* root) {
    if (!root) return; // 如果根节点为空,直接返回
    destroyTree(root->left); // 递归销毁左子树
    destroyTree(root->right); // 递归销毁右子树
    delete root; // 删除当前节点
}

int main() {
    vector<int> nodes = {1, 2, 3, -1, -1, 4, 5}; // 定义二叉树的先序遍历序列
    TreeNode* root = createTree(nodes, 0); // 创建二叉树
    vector<int> result; // 存储遍历结果的数组
    inorderTraversal(root, result); // 进行递归中序遍历
    for (int val : result) { // 输出遍历结果
        cout << val << " ";
    }
    cout << endl;

    destroyTree(root); // 销毁二叉树

    return 0;
}
迭代
#include <iostream>
#include <vector>
#include <stack>

using namespace std;

// 二叉树节点的定义
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

// 中序遍历
vector<int> inorderTraversal(TreeNode* root) {
    vector<int> result; // 存储遍历结果的数组
    stack<TreeNode*> st; // 辅助栈,用于存储遍历过程中的节点

    while (root != nullptr || !st.empty()) {
        while (root != nullptr) { // 将左子节点入栈直到为空
            st.push(root);
            root = root->left;
        }
        root = st.top(); // 弹出栈顶节点
        st.pop();
        result.push_back(root->val); // 将节点值加入结果数组
        root = root->right; // 处理右子节点
    }

    return result; // 返回中序遍历结果数组
}

// 创建二叉树
TreeNode* createTree(vector<int>& nodes, int index) {
    if (index >= nodes.size() || nodes[index] == -1) {
        return nullptr; // 如果节点为空,则返回nullptr
    }
    TreeNode* root = new TreeNode(nodes[index]); // 创建当前节点
    root->left = createTree(nodes, 2 * index + 1); // 创建左子树
    root->right = createTree(nodes, 2 * index + 2); // 创建右子树
    return root; // 返回当前节点
}

// 销毁二叉树
void destroyTree(TreeNode* root) {
    if (!root) return; // 如果根节点为空,直接返回
    destroyTree(root->left); // 递归销毁左子树
    destroyTree(root->right); // 递归销毁右子树
    delete root; // 删除当前节点
}

int main() {
    vector<int> nodes = {1, 2, 3, -1, -1, 4, 5}; // 定义二叉树的先序遍历序列
    TreeNode* root = createTree(nodes, 0); // 创建二叉树
    vector<int> result = inorderTraversal(root); // 进行中序遍历
    for (int val : result) { // 输出遍历结果
        cout << val << " ";
    }
    cout << endl;

    destroyTree(root); // 销毁二叉树

    return 0;
}
Java
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

public class Solution {
    /**
     * 中序遍历二叉树
     * @param root 二叉树的根节点
     * @return 中序遍历结果
     */
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>(); // 存储遍历结果的列表
        Stack<TreeNode> stack = new Stack<>(); // 辅助栈,用于遍历过程中节点的存储
        TreeNode curr = root; // 当前节点

        while (curr != null || !stack.isEmpty()) {
            while (curr != null) { // 将左子节点入栈直到为空
                stack.push(curr);
                curr = curr.left;
            }
            curr = stack.pop(); // 弹出栈顶节点
            result.add(curr.val); // 将节点值加入结果列表
            curr = curr.right; // 处理右子节点
        }

        return result; // 返回中序遍历结果列表
    }

    public static void main(String[] args) {
        int[] nodes = {1, 2, 3, -1, -1, 4, 5}; // 二叉树的先序遍历序列
        TreeNode root = createTree(nodes, 0); // 创建二叉树
        Solution solution = new Solution();
        List<Integer> result = solution.inorderTraversal(root); // 进行中序遍历
        for (int val : result) { // 输出遍历结果
            System.out.print(val + " ");
        }
        System.out.println();
    }

    /**
     * 根据先序遍历序列创建二叉树
     * @param nodes 二叉树的先序遍历序列
     * @param index 当前节点在序列中的索引
     * @return 创建的二叉树的根节点
     */
    private static TreeNode createTree(int[] nodes, int index) {
        if (index >= nodes.length || nodes[index] == -1) {
            return null; // 如果节点为空,则返回null
        }
        TreeNode root = new TreeNode(nodes[index]); // 创建当前节点
        root.left = createTree(nodes, 2 * index + 1); // 创建左子树
        root.right = createTree(nodes, 2 * index + 2); // 创建右子树
        return root; // 返回当前节点
    }
}
Python
# 二叉树节点的定义
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

def inorderTraversal(root):
    result = []  # 存储遍历结果的数组
    stack = []   # 辅助栈,用于存储遍历过程中的节点

    while root or stack:
        while root:  # 将左子节点入栈直到为空
            stack.append(root)
            root = root.left
        root = stack.pop()  # 弹出栈顶节点
        result.append(root.val)  # 将节点值加入结果数组
        root = root.right  # 处理右子节点

    return result  # 返回中序遍历结果数组

def createTree(nodes, index):
    if index >= len(nodes) or nodes[index] == -1:
        return None  # 如果节点为空,则返回None
    root = TreeNode(nodes[index])  # 创建当前节点
    root.left = createTree(nodes, 2 * index + 1)  # 创建左子树
    root.right = createTree(nodes, 2 * index + 2)  # 创建右子树
    return root  # 返回当前节点

def destroyTree(root):
    if not root:
        return  # 如果根节点为空,直接返回
    destroyTree(root.left)  # 递归销毁左子树
    destroyTree(root.right)  # 递归销毁右子树
    del root  # 删除当前节点

# 测试
nodes = [1, 2, 3, -1, -1, 4, 5]  # 定义二叉树的先序遍历序列
root = createTree(nodes, 0)  # 创建二叉树
result = inorderTraversal(root)  # 进行中序遍历
print(result)  # 输出遍历结果

destroyTree(root)  # 销毁二叉树
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值