玩转二叉树 审核通过

Wind_Rises 砂糖老师 2025-02-11 13:50:40 4

题解:构建二叉树并进行层序遍历

问题描述

给定二叉树的前序遍历和中序遍历,要求构建出原始的二叉树,并输出该二叉树的层序遍历。

思路分析

1. 二叉树的构建

  • 前序遍历:首先访问根节点,然后访问左子树,最后访问右子树。
  • 中序遍历:首先访问左子树,然后访问根节点,最后访问右子树。

根据前序遍历的第一个元素可以确定根节点,并利用中序遍历找到根节点在其中的位置,从而将中序遍历序列分为左右子树部分。接着递归处理左右子树,最终构建出完整的二叉树。

2. 二叉树的层序遍历

层序遍历使用队列进行遍历。首先将根节点入队,然后循环出队并访问当前节点,同时将该节点的左右子节点入队,直到队列为空。

代码实现

#include <bits/stdc++.h>
using namespace std;

const int N = 35;

struct node {
    int data;
    int left, right; // 使用数组存储左右子节点的下标
};

int n, pre[N], in[N], cnt = 0;
node tree[N]; // 存储二叉树节点的数组

// 构建二叉树的函数
int create(int prel, int prer, int inl, int inr) {
    if (prel > prer)
        return -1;  // 返回-1表示没有节点
    int rootIndex = prel;
    int rootValue = pre[rootIndex];
    int k = inl;
    // 在中序遍历中找到根节点的位置
    while (in[k] != rootValue) k++;
    int numleft = k - inl;
    int leftChild = create(prel + numleft + 1, prer, k + 1, inr); // 构建左子树
    int rightChild = create(prel + 1, prel + numleft, inl, k - 1); // 构建右子树

    tree[rootIndex].data = rootValue;
    tree[rootIndex].left = leftChild;
    tree[rootIndex].right = rightChild;
    return rootIndex;
}

// 层序遍历二叉树
void bfs(int root) {
    queue<int> q;
    q.push(root);
    while (!q.empty()) {
        int now = q.front();
        q.pop();
        printf("%d", tree[now].data);
        if (++cnt < n)
            printf(" ");
        // 将左右子节点入队
        if (tree[now].left != -1)
            q.push(tree[now].left);
        if (tree[now].right != -1)
            q.push(tree[now].right);
    }
}

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &in[i]);
    for (int i = 0; i < n; i++) scanf("%d", &pre[i]);
    int root = create(0, n - 1, 0, n - 1);
    bfs(root);
    return 0;
}

代码解析

  1. node 结构体
struct node {
    int data;
    int left, right; // 使用数组存储左右子节点的下标
};

我们使用结构体 node 来表示二叉树的每个节点。每个节点包含:

data:节点的值 left:左子节点的下标 right:右子节点的下标 left 和 right 的值为 -1 时表示该子节点不存在。

  1. create 函数
int create(int prel, int prer, int inl, int inr) {
    if (prel > prer)
        return -1;  // 返回-1表示没有节点
    int rootIndex = prel;
    int rootValue = pre[rootIndex];
    int k = inl;
    while (in[k] != rootValue) k++;
    int numleft = k - inl;
    int leftChild = create(prel + numleft + 1, prer, k + 1, inr); // 构建左子树
    int rightChild = create(prel + 1, prel + numleft, inl, k - 1); // 构建右子树

    tree[rootIndex].data = rootValue;
    tree[rootIndex].left = leftChild;
    tree[rootIndex].right = rightChild;
    return rootIndex;
}

该函数通过递归方式根据前序和中序遍历结果构建二叉树。具体步骤:

从前序遍历中选择根节点。 在中序遍历中找到根节点的位置,将序列分为左子树和右子树。 对左子树和右子树递归调用 create 函数构建其左右子节点。 3. bfs 函数

void bfs(int root) {
    queue<int> q;
    q.push(root);
    while (!q.empty()) {
        int now = q.front();
        q.pop();
        printf("%d", tree[now].data);
        if (++cnt < n)
            printf(" ");
        if (tree[now].left != -1)
            q.push(tree[now].left);
        if (tree[now].right != -1)
            q.push(tree[now].right);
    }
}

该函数实现层序遍历,使用队列模拟。步骤如下:

将根节点加入队列。 依次访问队列中的节点,输出节点的值。 若当前节点有左子节点,将左子节点加入队列;若有右子节点,则将右子节点加入队列。 重复直到队列为空。 4. 主函数

int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) scanf("%d", &in[i]);
    for (int i = 0; i < n; i++) scanf("%d", &pre[i]);
    int root = create(0, n - 1, 0, n - 1);
    bfs(root);
    return 0;
}

主函数中:

输入节点数量 n,然后输入前序和中序遍历序列。 调用 create 函数构建二叉树。 调用 bfs 函数输出层序遍历结果。 总结 本题的关键是通过前序和中序遍历来构建二叉树,然后通过层序遍历输出二叉树的结果。通过递归构建树和队列进行层序遍历是常见的树形问题解法。

{{ vote && vote.total.up }}