找出直系亲属-cpp

一、题目描述

如果A,B是C的父母亲,则A,B是C的parent,C是A,B的child,如果A,B是C的(外)祖父,祖母,则A,B是C的grandparent,C是A,B的grandchild,如果A,B是C的(外)曾祖父,曾祖母,则A,B是C的great-grandparent,C是A,B的great-grandchild,之后再多一辈,则在关系上加一个great-。

输入描述:
输入包含多组测试用例,每组用例首先包含2个整数n(0<=n<=26)和m(0<m<50), 分别表示有n个亲属关系和m个问题, 然后接下来是n行的形式如ABC的字符串,表示A的父母亲分别是B和C,如果A的父母亲信息不全,则用-代替,例如A-C,再然后是m行形式如FA的字符串,表示询问F和A的关系。
输出描述:
如果询问的2个人是直系亲属,请按题目描述输出2者的关系,如果没有直系关系,请输出-。 具体含义和输出格式参见样例.
示例1
输入:

3 2
ABC
CDE
EFG
FA
BE

输出:

great-grandparent
-

二、思路和代码

思路:通过输入的关系构建树,用map存每个char对应的树节点指针。再向上或向下查询该树便可。(注释详细)

注意点:
1.每次使用指针时应该考虑是否为NULL
2.用char数组接收输入时应该多一位结束位,如输入ab应该用size为3的数组。
3.几种接收输入的方式:cin.get(字符数组名,接收字符数);cin.getline(接受字符串到m,接受个数5,结束字符),第三个参数默认为\0;cin>>;

#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;

// 思路:构建树,搜索。用map存每个树结点的指针
// 结构体的初始化函数
typedef struct node {
    char value;
    node* fa;
    node* mo;
    vector<node*> child;
    node(char va, node* f, node* m) {
        this->value = va;
        this->fa = f;
        this->mo = m;
    }
}node;

// 向上搜索,返回辈分差,若都找不到,返回-1
int searchUp(node* cur, node* obj) {
    //没找到
    if (cur == NULL) {
        return -1;
    }
    //找到了
    else if (cur->value == obj->value) {
        return 0;
    }
    else {
        int temp = searchUp(cur->fa, obj);
        int temp0 = searchUp(cur->mo, obj);
        if (temp != -1)
            return temp + 1;
        if (temp0 != -1)
            return temp0 + 1;
        return -1;
    }
}

// 向下搜索,返回辈分差,若都找不到,返回-1
int searchDown(node* cur, node* obj) {
    //没找到
    if (cur == NULL) {
        return -1;
    }
    //找到了
    else if (cur->value == obj->value) {
        return 0;
    }
    else {
        int res;
        for (int i = 0; i < cur->child.size();i++) {
            res = searchDown(cur->child[i], obj);
            //找到了
            if (res != -1)
                return res + 1;
        }
        //没找到
        return -1;
    }
}
int main() {
    int x, y;
    cin >> x >> y;
    //接收每行输入,构建树,默认结点名不重复
    char temp[4];
    //ma存char与结点指针的映射
    map<char, node*> ma;
    for (int i = 0;i < x;i++) {
        cin >> temp;
        //构建三个节点,记录在ma中,有结点可能已经存在,tempnode分别为child,father,mother
        node* tempnode[3];
        for (int j = 0;j < 3;j++) {
            if (temp[j] == '-') {
                tempnode[j] = NULL;
                continue;
            }
            if (ma.find(temp[j]) != ma.end()) {
                tempnode[j] = ma[temp[j]];
            }
            else {
                tempnode[j] = new node(temp[j], NULL, NULL);
                ma[temp[j]] = tempnode[j];
            }
        }
        //建立连接
        tempnode[0]->fa = tempnode[1];
        tempnode[0]->mo = tempnode[2];
        //使用指针时记得考虑是否为NULL
        if(tempnode[1]!=NULL)
            tempnode[1]->child.emplace_back(tempnode[0]);
        if(tempnode[2]!=NULL)
            tempnode[2]->child.emplace_back(tempnode[0]);
    }

    //查找树
    char temp0[3];
    node* first;
    node* second;
    int res;
    string resstr;
    for (int i = 0;i < y;i++) {
        cin >> temp0;
        // 从第一个结点开始向上或向下搜索

        //向上搜索
        first = ma[temp0[0]];
        second = ma[temp0[1]];
        res = searchUp(first, second);
        // 搜到了
        if (res != -1) {
            resstr = "child";
            res -= 1;
            if (res >= 1) {
                resstr = "grand" + resstr;
                res -= 1;
            }
            for (int j = 0;j < res;j++) {
                resstr = "great-" + resstr;
            }
            cout << resstr<<"\n";
        }
        // 没搜到
        else {
            // 向下搜索
            res = searchDown(first, second);
            //没搜到
            if (res == -1) {
                cout << "-"<<"\n";
            }
            else {
                resstr = "parent";
                res -= 1;
                if (res >= 1) {
                    resstr = "grand" + resstr;
                    res -= 1;
                }
                for (int j = 0;j < res;j++) {
                    resstr = "great-" + resstr;
                }
                cout << resstr<<"\n";
            }
        }

    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值