题解 | #先序遍历、中序遍历和后序遍历#

先序遍历、中序遍历和后序遍历

https://www.nowcoder.com/practice/15fdb346838545d0b272e43957e1cb2a

题目链接

先序遍历、中序遍历和后序遍历

题目描述

给定一棵包含 个节点的二叉树,以 条有向边 (父节点指向子节点)的形式给出。子节点的左右关系需要根据以下规则确定:

  1. 若父节点有两个孩子,编号较小者为左孩子,较大者为右孩子。

  2. 若父节点只有一个孩子:

    • 若子节点编号大于父节点编号,则该孩子为左孩子。
    • 否则(子节点编号小于父节点编号),该孩子为右孩子。

你需要输出该二叉树的先序、中序、后序遍历序列。

解题思路

本题的解法分为两个主要步骤:1. 重建二叉树结构2. 执行标准遍历

1. 重建二叉树

首先,我们需要根据输入的父子关系和给定的左右孩子规则,构建出完整的二叉树。

  • 寻找根节点

    树的根节点是唯一没有父节点的节点。我们可以通过计算每个节点的入度来找到它。遍历所有 条边 的入度加一。最后,入度为 的那个节点就是根。

  • 确定左右孩子

    a. 我们先用一个临时的邻接表(例如 )来存储每个节点的所有孩子,暂时不区分左右。

    b. 然后,遍历所有节点 (从 ),查看 列表:

    有两个孩子:对 进行排序,第一个(较小的)是左孩子,第二个(较大的)是右孩子。

    只有一个孩子 :根据规则 ,判断 是左孩子还是右孩子。

    没有孩子:该节点是叶子节点。

    c. 将最终确定的左右孩子关系存储在两个数组 中。 存储节点 的左孩子编号, 存储右孩子编号。没有孩子则记为

2. 执行遍历

当二叉树的结构(即每个节点的左右孩子是谁)完全确定后,我们就可以从根节点开始,执行三种经典的深度优先遍历:

  • 先序遍历 (Pre-order): 访问顺序是 左子树 右子树

  • 中序遍历 (In-order): 访问顺序是 左子树 右子树

  • 后序遍历 (Post-order): 访问顺序是 左子树 右子树

这三种遍历都可以通过简单的递归函数实现。每个函数都接收一个当前节点作为参数,并按照各自的顺序递归调用自身处理左右子树,并在合适的时机将当前节点的值存入结果列表。

最后,按顺序输出三个遍历结果列表即可。

代码

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int left_child[100005], right_child[100005];
vector<int> pre_order_result, in_order_result, post_order_result;

void pre_order(int u) {
    if (u == 0) return;
    pre_order_result.push_back(u);
    pre_order(left_child[u]);
    pre_order(right_child[u]);
}

void in_order(int u) {
    if (u == 0) return;
    in_order(left_child[u]);
    in_order_result.push_back(u);
    in_order(right_child[u]);
}

void post_order(int u) {
    if (u == 0) return;
    post_order(left_child[u]);
    post_order(right_child[u]);
    post_order_result.push_back(u);
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;

    vector<int> in_degree(n + 1, 0);
    vector<vector<int>> children(n + 1);
    for (int i = 0; i < n - 1; ++i) {
        int u, v;
        cin >> u >> v;
        children[u].push_back(v);
        in_degree[v]++;
    }

    int root = -1;
    for (int i = 1; i <= n; ++i) {
        if (in_degree[i] == 0) {
            root = i;
            break;
        }
    }

    for (int i = 1; i <= n; ++i) {
        if (children[i].empty()) continue;
        if (children[i].size() == 2) {
            sort(children[i].begin(), children[i].end());
            left_child[i] = children[i][0];
            right_child[i] = children[i][1];
        } else { // size == 1
            int child = children[i][0];
            if (child > i) {
                left_child[i] = child;
            } else {
                right_child[i] = child;
            }
        }
    }

    pre_order(root);
    in_order(root);
    post_order(root);

    for (int i = 0; i < n; ++i) cout << pre_order_result[i] << (i == n - 1 ? "" : " ");
    cout << "\n";
    for (int i = 0; i < n; ++i) cout << in_order_result[i] << (i == n - 1 ? "" : " ");
    cout << "\n";
    for (int i = 0; i < n; ++i) cout << post_order_result[i] << (i == n - 1 ? "" : " ");
    cout << "\n";

    return 0;
}
import java.util.*;

public class Main {
    static int[] leftChild, rightChild;
    static List<Integer> preOrderResult, inOrderResult, postOrderResult;

    public static void preOrder(int u) {
        if (u == 0) return;
        preOrderResult.add(u);
        preOrder(leftChild[u]);
        preOrder(rightChild[u]);
    }

    public static void inOrder(int u) {
        if (u == 0) return;
        inOrder(leftChild[u]);
        inOrderResult.add(u);
        inOrder(rightChild[u]);
    }

    public static void postOrder(int u) {
        if (u == 0) return;
        postOrder(leftChild[u]);
        postOrder(rightChild[u]);
        postOrderResult.add(u);
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();

        int[] inDegree = new int[n + 1];
        List<Integer>[] children = new ArrayList[n + 1];
        for (int i = 1; i <= n; i++) {
            children[i] = new ArrayList<>();
        }

        for (int i = 0; i < n - 1; i++) {
            int u = sc.nextInt();
            int v = sc.nextInt();
            children[u].add(v);
            inDegree[v]++;
        }

        int root = -1;
        for (int i = 1; i <= n; i++) {
            if (inDegree[i] == 0) {
                root = i;
                break;
            }
        }

        leftChild = new int[n + 1];
        rightChild = new int[n + 1];

        for (int i = 1; i <= n; i++) {
            if (children[i].isEmpty()) continue;
            if (children[i].size() == 2) {
                Collections.sort(children[i]);
                leftChild[i] = children[i].get(0);
                rightChild[i] = children[i].get(1);
            } else { // size == 1
                int child = children[i].get(0);
                if (child > i) {
                    leftChild[i] = child;
                } else {
                    rightChild[i] = child;
                }
            }
        }

        preOrderResult = new ArrayList<>();
        inOrderResult = new ArrayList<>();
        postOrderResult = new ArrayList<>();

        preOrder(root);
        inOrder(root);
        postOrder(root);

        for (int i = 0; i < n; i++) System.out.print(preOrderResult.get(i) + (i == n - 1 ? "" : " "));
        System.out.println();
        for (int i = 0; i < n; i++) System.out.print(inOrderResult.get(i) + (i == n - 1 ? "" : " "));
        System.out.println();
        for (int i = 0; i < n; i++) System.out.print(postOrderResult.get(i) + (i == n - 1 ? "" : " "));
        System.out.println();
    }
}
import sys

# 增加递归深度限制
sys.setrecursionlimit(100005)

def solve():
    n_str = sys.stdin.readline()
    if not n_str: return
    n = int(n_str)
    if n == 0: return

    in_degree = [0] * (n + 1)
    children = [[] for _ in range(n + 1)]
    
    edges = []
    for _ in range(n - 1):
        edges.append(list(map(int, sys.stdin.readline().split())))

    for u, v in edges:
        children[u].append(v)
        in_degree[v] += 1
        
    root = -1
    for i in range(1, n + 1):
        if in_degree[i] == 0:
            root = i
            break
    
    left_child = [0] * (n + 1)
    right_child = [0] * (n + 1)
    
    for i in range(1, n + 1):
        if not children[i]: continue
        if len(children[i]) == 2:
            children[i].sort()
            left_child[i] = children[i][0]
            right_child[i] = children[i][1]
        else: # len == 1
            child = children[i][0]
            if child > i:
                left_child[i] = child
            else:
                right_child[i] = child

    pre_order_result = []
    in_order_result = []
    post_order_result = []

    def pre_order(u):
        if u == 0: return
        pre_order_result.append(u)
        pre_order(left_child[u])
        pre_order(right_child[u])

    def in_order(u):
        if u == 0: return
        in_order(left_child[u])
        in_order_result.append(u)
        in_order(right_child[u])

    def post_order(u):
        if u == 0: return
        post_order(left_child[u])
        post_order(right_child[u])
        post_order_result.append(u)

    pre_order(root)
    in_order(root)
    post_order(root)

    print(*pre_order_result)
    print(*in_order_result)
    print(*post_order_result)

solve()

算法及复杂度

  • 算法:构建邻接表、根据规则确定左右孩子、递归进行三种DFS遍历。

  • 时间复杂度:

    • 读入数据、计算入度、构建初始邻接表,需要

    • 寻找根节点需要

    • 遍历所有节点确定左右孩子关系,总共访问所有边一次,复杂度为

    • 三次遍历(先序、中序、后序)都分别访问每个节点一次,总共是

    • 总体时间复杂度为

  • 空间复杂度:

    • 需要空间存储入度、临时邻接表、左右孩子数组以及遍历结果,都是

    • 递归遍历的调用栈深度在最坏情况下(链状树)也是

全部评论

相关推荐

在投简历的柠檬精很想...:可以明确说,问的东西几乎是简历上的东西。你写的确实有点模糊。面试可能会问你一些常用的通信的问题,差分信号走线之类的,单片机最小系统啥的,模电,数电,基本电源,buck,boost,ldo之类的吧。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务