解析:这题主要考察二叉树的遍历,但是我们学习二叉树的时候我们都是使用二叉链表完成操作,这题如果还是用二叉链表,会很麻烦,因为给定的边两个结点你是不知道有没有之前创建了结点!所有我们要换一个思路,既然给定的点编号刚好是1~n那么我们直接用邻接矩阵存边的关系,第一个下标是弧尾,每一个结点后面挂一个孩子也就是弧头。我们也要边插入边统计入度,便于找到根节点,根节点的入度为0!

这里第一个代码是先存好边,然后再遍历的时候调整左右孩子的位置。注意到先序:根左右和后序:左右根,都是“左右”所以直接排序满足条件即可,根的遍历要么在孩子之前要么在孩子之后。但是中序遍历需要特殊处理,因为有只有一个孩子的情况且与父亲结点要满足关系,所以单独处理一个结点情况,两个结点还是满足“左根右”直接递归 输出 递归即可。

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

void solve() {
    int n;
    cin >> n;
    vector<vector<int>>g(n + 1); //邻接表存图
    vector<int>in(n + 1); //统计每个结点的入度,找出根节点
    int a, b;
    for (int i = 1; i <= n - 1; i++) {
        cin >> a >> b;
        g[a].push_back(b);
        in[b]++;
    }

    int root = -1;
    for (int i = 1; i <= n; i++) {
        if (in[i] == 0) { //找到入度为0的结点,即为根结点
            root = i;
        }
        sort(g[i].begin(), g[i].end());
    }

    auto preOrder = [&](auto&& self, int root)->void{
        //先序遍历序列 根 左 右
        cout << root << " ";
        for (auto p : g[root]) {
            self(self, p);
        }
    };
    preOrder(preOrder, root);
    cout << endl;

    auto inOrder = [&](auto&& self, int root)->void{
        //中序遍历序列 左 根 右
        if(g[root].size()==0){//叶子结点直接返回
            cout<<root<<" ";
            return;
        }else if(g[root].size()==1){//只有一个孩子
            if(g[root][0]>root){//做左孩子
                self(self,g[root][0]);
                cout<<root<<" ";
            }else{//做右孩子
                cout<<root<<" ";
                self(self,g[root][0]);
            }
        }else{//有两个孩子
            self(self,g[root][0]);
            cout<<root<<" ";
            self(self,g[root][1]);
        }
    };
    inOrder(inOrder, root);
    cout << endl;

    auto reOrder = [&](auto&& self, int root)->void{
        //后序遍历序列 左 右 根
        for (auto p : g[root]) {
            self(self, p);
        }
        cout << root << " ";
    };
    reOrder(reOrder, root);
    cout << endl;
}

signed main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    solve();
    return 0;
}

第二套代码是先处理好边的关系,再遍历。符号我们学二叉树遍历的逻辑。但是存储孩子用了哈希表暂存一下,再具体把左右孩子分别用数组存储(按照题设要求哟~),代表该下标的左右孩子。也要在存边的时候找到根节点!!!遍历时直接套数据结构的模板即可。特别注意一定要返回哟~这里数组元素为0代表是空结点哦!!!会爆栈的!

#include<bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define int long long

void solve() {
    int n;
    cin >> n;
    unordered_map<int, vector<int>>mp; //直接先存下所有孩子
    //存树结构判断满足条件左右孩子
    vector<int>l(n + 1);
    vector<int>r(n + 1);
    vector<bool>hasFa(n+1);
    int a, b;
    for (int i = 1; i <= n - 1; i++) {
        cin >> a >> b;
        mp[a].push_back(b);
        hasFa[b]=true;
    }
    int root = -1;
    for (int i = 1; i <= n; i++) {
        if (hasFa[i]==false) {
            root = i;
        } 
        if (mp[i].size() == 1) {
            if (mp[i][0] > i) {
                l[i] = mp[i][0];
            } else r[i] = mp[i][0];
        } else if(mp[i].size()==2){
            l[i] = min(mp[i][0], mp[i][1]);
            r[i] = max(mp[i][0], mp[i][1]);
        }
    }

    auto PreOrder = [&](auto&& self, int root)->void{
        //根 左 右
        cout << root << " ";
        if(l[root]!=0)self(self, l[root]);
        if(r[root]!=0)self(self, r[root]);
    };
    PreOrder(PreOrder, root);
    cout << endl;

    auto InOrder = [&](auto&& self, int root)->void{
        //左 根 右
        if(l[root]!=0)self(self, l[root]);
        cout << root << " ";
        if(r[root]!=0)self(self, r[root]);
    };
    InOrder(InOrder, root);
    cout << endl;

    auto ReOrder = [&](auto&& self, int root)->void{
        //左 右 根
        if(l[root]!=0)self(self, l[root]);
        if(r[root]!=0)self(self, r[root]);
        cout << root << " ";
    };
    ReOrder(ReOrder, root);
    cout << endl;
}

signed main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    solve();
    return 0;
}