2019北航机考第二题题目描述解析以及参考代码(紧接第一题)

题目描述:一个关于三叉树的题目,小于100的值代表树叶,大于100的值为分支点,建树的过程是水平方向建树,输入格式:

先输入n,代表有n组数据,接下来n行,输入4个数,第一个数代表根节点,接下来分别代表三个子节点,-1代表子节点不存在,输入的顺序按照层次遍历的次序。接下来,要求寻找叶子节点的最短路径,最短路径是指不经过重复的边。输入方式,首先输入一个值m,代表m行,接下来m行输入m个叶子节点和对应的优先级,要求按优先级输出从上次到达的位置到该节点的最短路径,每条路径的最后一个节点要求输出目标叶子节点,最后要求回到根节点。

示例输入:10

                   100 101 108 107

                    101 1 102 2

                     108 103 104 105

                     107 17 109 18

                      102 3 4 5

                      103 7 8 9

                      104 10 106 11

                       105 15 16 -1

                       109 19 20 21

                      106 12 13 14

                       5

                       8 1

                       14 3

                       16 2

                        5 0

                        19 4

样例输出:100 101 102 5

                   102 101 100 108 103 8

                    103 108 105 16

                    105 108 104 106 14

                     106 104 108 100 107 109 19

                      109 107 100

这是建立的树:

思路解析:

第一步肯定是建树,声明数据结构,利用队列建树

#include<iostream>
#include<stdio.h>
#include<queue>
using namespace std;

struct triTree{
    int data;
    struct triTree *lchild;
    struct triTree *mchild;
    struct triTree *rchild;
    struct triTree *parent;
    triTree()
    {
        lchild = NULL;
        mchild = NULL;
        rchild = NULL;
        parent = NULL;
    }
    triTree(int x)
    {
        data = x;
        lchild = NULL;
        mchild = NULL;
        rchild = NULL;
        parent = NULL;
    }

};
queue<triTree*> q;
triTree* createTree(triTree* root,int rt,int a,int b,int c)
{
    if(root->parent==NULL)
    {
        root->data= rt;
    }
    if(a!=-1){
        triTree *newNode = new triTree(a);
        root->lchild = newNode;
        newNode->parent = root;
        if(newNode->data>=100) q.push(newNode);
    }else root->lchild = NULL;
    if(b!=-1){
         triTree *newNode = new triTree(b);
        root->mchild = newNode;
        newNode->parent = root;
        if(newNode->data>=100) q.push(newNode);
    }else root->mchild = NULL;
    if(c!=-1){
         triTree *newNode = new triTree(c);
        root->rchild = newNode;
        newNode->parent = root;
        if(newNode->data>=100) q.push(newNode);
    }else root->rchild = NULL;
    if(!q.empty()){
        triTree* tmp = q.front();
        q.pop();
        return tmp;
    }else return NULL;

}
//void pre_test(triTree* test)
//{
//    if(test==NULL) return;
//    cout<<test->data<<" ";
//    pre_test(test->lchild);
//    pre_test(test->mchild);
//    pre_test(test->rchild);
//}
int main()
{
    freopen("in.txt","r",stdin);
    int n;
    cin>>n;
    int rt,a,b,c;
    struct triTree* root = new triTree;
    struct triTree* tmp = root;
    for(int i=0;i<n;i++)
    {
        cin>>rt>>a>>b>>c;
        tmp = createTree(tmp,rt,a,b,c);
    }
    //pre_test(root);

}

第二步处理下一组输入,并且排序

struct target{
    int target;
    int priority;
    bool operator<( const struct target& t)const
    {
        return priority<t.priority;
    }
};
    int m;
    cin>>m;
    target  t[m];
    for(int i=0;i<m;i++)
    {
        cin>>t[i].target>>t[i].priority;
    }
    sort(t,t+m);

第三步,需要四个函数,需要从输入的节点值获取在树中的节点地址(指针),根据两个节点后序遍历求最近的公共父节点,

从公共节点出发前序遍历找到目标路径的节点和打印函数。

struct triTree* search_node(triTree* root,int x)
{
    if(root==NULL||root->data==x) return root;
    struct triTree* tmp = search_node(root->lchild,x);
    if(tmp!=NULL) return tmp;
    else tmp = search_node(root->mchild,x);
    if(tmp!=NULL) return tmp;
    else tmp = search_node(root->rchild,x);
    if(tmp!=NULL) return tmp;
    else return NULL;


}
struct triTree* getNearestRoot(triTree* root,triTree* node1,triTree *node2)
{
    if(root==NULL||root==node1||root==node2) return root;
    triTree* left = getNearestRoot(root->lchild,node1,node2);
    triTree* middle = getNearestRoot(root->mchild,node1,node2);
    triTree* right = getNearestRoot(root->rchild,node1,node2);
    if(left!=NULL&&middle!=NULL) return root;
    if(left!=NULL&&right!=NULL) return root;
    if(middle!=NULL&&right!=NULL) return root;
    if(left!=NULL) return left;
    if(middle!=NULL) return middle;
    if(right!=NULL) return right;
    return NULL;
}
vector<int> result;
triTree* preOrder(triTree* root,int x)
{

    if(root==NULL||root->data==x) return root;
    result.push_back(root->data);
    triTree* tmp = preOrder(root->lchild,x);
    if(root->lchild==NULL);
    else if(tmp==NULL||tmp->data!=x) result.pop_back();
    else return tmp;
    tmp = preOrder(root->mchild,x);
    if(root->mchild==NULL);
    else if(tmp==NULL||tmp->data!=x) result.pop_back();
    else return tmp;
    tmp = preOrder(root->rchild,x);
    if(root->rchild==NULL);
    else if(tmp==NULL||tmp->data!=x) result.pop_back();
    else return tmp;

}

void print()
{
    int len = result.size();
    for(int i=0;i<len;i++)
    {
        cout<<result[i]<<" ";
    }
}

第四步:按照输出格式进行输出即可

triTree *tmp1 = root;
    triTree *tmp2,*troot;
    triTree *last = root;
    for(int i=0;i<m;i++)
    {
        result.clear();

        tmp2 = search_node(root,t[i].target);
        troot = getNearestRoot(root,tmp1,tmp2);
        while(last!=troot)
        {
             result.push_back(last->data);
             last = last->parent;
        }
        preOrder(troot,t[i].target);
        print();
        cout<<tmp2->data<<" "<<endl;
        tmp1 = tmp2;
        last = search_node(root,result.back());
    }
    while(last!=NULL)
    {
        cout<<last->data<<" ";
        last = last->parent;
    }
    cout<<endl;

这里给出全部代码(注释掉的代码是为了调试,无意义)

#include<iostream>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;

struct triTree{
    int data;
    struct triTree *lchild;
    struct triTree *mchild;
    struct triTree *rchild;
    struct triTree *parent;
    triTree()
    {
        lchild = NULL;
        mchild = NULL;
        rchild = NULL;
        parent = NULL;
    }
    triTree(int x)
    {
        data = x;
        lchild = NULL;
        mchild = NULL;
        rchild = NULL;
        parent = NULL;
    }

};
queue<triTree*> q;
vector<int> result;
triTree* createTree(triTree* root,int rt,int a,int b,int c)
{
    if(root->parent==NULL)
    {
        root->data= rt;
    }
    if(a!=-1){
        triTree *newNode = new triTree(a);
        root->lchild = newNode;
        newNode->parent = root;
        if(newNode->data>=100) q.push(newNode);
    }else root->lchild = NULL;
    if(b!=-1){
         triTree *newNode = new triTree(b);
        root->mchild = newNode;
        newNode->parent = root;
        if(newNode->data>=100) q.push(newNode);
    }else root->mchild = NULL;
    if(c!=-1){
         triTree *newNode = new triTree(c);
        root->rchild = newNode;
        newNode->parent = root;
        if(newNode->data>=100) q.push(newNode);
    }else root->rchild = NULL;
    if(!q.empty()){
        triTree* tmp = q.front();
        q.pop();
        return tmp;
    }else return NULL;

}
//void pre_test(triTree* test)
//{
//    if(test==NULL) return;
//    cout<<test->data<<" ";
//    pre_test(test->lchild);
//    pre_test(test->mchild);
//    pre_test(test->rchild);
//}
struct target{
    int target;
    int priority;
    bool operator<( const struct target& t)const
    {
        return priority<t.priority;
    }
};
struct triTree* search_node(triTree* root,int x)
{
    if(root==NULL||root->data==x) return root;
    struct triTree* tmp = search_node(root->lchild,x);
    if(tmp!=NULL) return tmp;
    else tmp = search_node(root->mchild,x);
    if(tmp!=NULL) return tmp;
    else tmp = search_node(root->rchild,x);
    if(tmp!=NULL) return tmp;
    else return NULL;


}
struct triTree* getNearestRoot(triTree* root,triTree* node1,triTree *node2)
{
    if(root==NULL||root==node1||root==node2) return root;
    triTree* left = getNearestRoot(root->lchild,node1,node2);
    triTree* middle = getNearestRoot(root->mchild,node1,node2);
    triTree* right = getNearestRoot(root->rchild,node1,node2);
    if(left!=NULL&&middle!=NULL) return root;
    if(left!=NULL&&right!=NULL) return root;
    if(middle!=NULL&&right!=NULL) return root;
    if(left!=NULL) return left;
    if(middle!=NULL) return middle;
    if(right!=NULL) return right;
    return NULL;
}
void print()
{
    int len = result.size();
    for(int i=0;i<len;i++)
    {
        cout<<result[i]<<" ";
    }
}
triTree* preOrder(triTree* root,int x)
{

    if(root==NULL||root->data==x) return root;
    result.push_back(root->data);
    triTree* tmp = preOrder(root->lchild,x);
    if(root->lchild==NULL);
    else if(tmp==NULL||tmp->data!=x) result.pop_back();
    else return tmp;
    tmp = preOrder(root->mchild,x);
    if(root->mchild==NULL);
    else if(tmp==NULL||tmp->data!=x) result.pop_back();
    else return tmp;
    tmp = preOrder(root->rchild,x);
    if(root->rchild==NULL);
    else if(tmp==NULL||tmp->data!=x) result.pop_back();
    else return tmp;

}

int main()
{
    //freopen("in.txt","r",stdin);
    int n;
    cin>>n;
    int rt,a,b,c;
    struct triTree* root = new triTree;
    struct triTree* tmp = root;
    for(int i=0;i<n;i++)
    {
        cin>>rt>>a>>b>>c;
        tmp = createTree(tmp,rt,a,b,c);
    }
    //pre_test(root);
    int m;
    cin>>m;
    target  t[m];
    for(int i=0;i<m;i++)
    {
        cin>>t[i].target>>t[i].priority;
    }
    sort(t,t+m);
//    for(int i=0;i<m;i++)
//    {
//        cout<<t[i].target<<" "<<t[i].priority<<endl;
//    }
//    triTree * node1 = search_node(root,15);
    cout<<node->data<<" "<<node->parent->data<<endl;
//    triTree *node2 = search_node(root,19);
//    triTree *res = getNearestRoot(root,node1,node2);
//    cout<<res->data<<endl;
//    result.clear();
//    preOrder(root,7);
//    print();
    triTree *tmp1 = root;
    triTree *tmp2,*troot;
    triTree *last = root;
    for(int i=0;i<m;i++)
    {
        result.clear();

        tmp2 = search_node(root,t[i].target);
        troot = getNearestRoot(root,tmp1,tmp2);
        while(last!=troot)
        {
             result.push_back(last->data);
             last = last->parent;
        }
        preOrder(troot,t[i].target);
        print();
        cout<<tmp2->data<<" "<<endl;
        tmp1 = tmp2;
        last = search_node(root,result.back());
    }
    while(last!=NULL)
    {
        cout<<last->data<<" ";
        last = last->parent;
    }
    cout<<endl;
}

点评:这个题按以上分析,十分复杂,考察的点非常多,要求关于树的常用算法非常熟悉才可以在最多一个半小时完成。这里说一说都用到哪些数据结构和算法:首先是三叉树的数据结构,(为了处理方便增加parent指针),树的建立过程(用队列),结构体排序(sort函数以及操作符重载),前序遍历求节点,后序遍历求两个节点的最近公共父节点,前序遍历求叶子节点的路径等,细节非常多。近两年北航机考最后一题都是关于树有关的,难度都不低,建议决定报考北航的考生注意这一部分程序设计的实战。

转载请注明出处

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值