DS树--找出直系亲属

Description

如果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-

Input

输入包含多组测试用例,每组用例首先包含2个整数n(0<=n<=26)和m(0<m<50), 分别表示有n个亲属关系和m个问题, 然后接下来是n行的形式如ABC的字符串,表示A的父母亲分别是B和C,如果A的父母亲信息不全,则用-代替,例如A-C,再然后是m行形式如FA的字符串,表示询问F和A的关系。 当n和m为0时结束输入。

Output

如果询问的2个人是直系亲属,请按题目描述输出2者的关系,如果没有直系关系,请输出-。 具体含义和输出格式参见样例.

Sample

Input

Output

3 2
ABC
CDE
EFG
FA
BE
0 0
great-grandparent
-
4 3
ABH
BCD
DEF
EWY
BF
CH
AW
0 0
grandchild
-
great-great-grandchild

思路:

首先建树。我的想法是按题目所给的三个字符的关系来建一部分树,然后再组合到整体的树中。

然后在建好的树中去找关系。为了方便,两个节点就一直往上找父母亲,谁能找到对方就能确定关系。

(详细请看代码,已写了充足的注释)

代码实现:

#include <iostream>
#include <queue>

using namespace std;

class btnode
{
public:
    char data;                               // 数据
    btnode *leftChild, *rightChild, *parent; // 指针 (此处left,rigth表示父母,parent才是子代)
    btnode() : leftChild(NULL), rightChild(NULL), parent(NULL) {}
    ~btnode()
    {
        delete leftChild;
        delete rightChild;
        delete parent;
    }
};

class BinaryTree
{
private:
    btnode *root = NULL; // 根

public:
    BinaryTree() : root(NULL){};
    btnode *findNode(char ch);              //寻找节点
    void part(string str);                  //部分建树
    void relationship(char fir, char sec);  //查找关系
};

//寻找节点,这里我用的是层次遍历的方法,检测到有对应的节点就返还该节点的指针,无则返回空指针。
btnode *BinaryTree::findNode(char ch)
{
    btnode *t = root;
    btnode *ans = nullptr;
    queue<btnode *> dt;

    dt.push(t);

    while (root && !dt.empty())
    {
        if (ch == dt.front()->data)
        {
            ans = dt.front();
            break;
        }
        if (dt.front()->leftChild)
            dt.push(dt.front()->leftChild);
        if (dt.front()->rightChild)
            dt.push(dt.front()->rightChild);
        dt.pop();
    }

    return ans;
}

//部分建树,按题目所给字符串分为子代和父母亲三部分,而后进行连接
void BinaryTree::part(string str)
{
    btnode *p[3], *temp;

    for (int i = 0; i < 3; i++) //三部分
    {
        temp = findNode(str[i]); //查找对应的字符
        
        if (i == 0 && !root) //检测根节点是否存在,没有就建立根节点
        {
            root = new btnode();
            root->data = str[0];
            p[0] = root;
        }
        else if (temp) //检测所查找的字符是否已经存在树中,有则将其与其他部分与其链接,无则新建。
        {
            p[i] = temp;
            if (temp == root) //检测根节点是否为父母一方,是则改变根节点为该新建的部分树的子代。
                root = p[0];
        }
        else
        {
            p[i] = new btnode();
            p[i]->data = str[i];
        }
    }

    //进行连接
    p[0]->leftChild = p[1];
    p[0]->rightChild = p[2];
    p[1]->parent = p[0];
    p[2]->parent = p[0];
}


//查找关系
void BinaryTree::relationship(char fir, char sec)
{
    btnode *p[2] = {findNode(fir), findNode(sec)};
    char ch[2] = {sec, fir};

    int count;
    int flag = -1;

    for (int i = 0; i < 2; i++)
    {
        //计数
        count = 0;

        //两次都向上查找
        while (p[i]->parent)
        {
            count++;
            p[i] = p[i]->parent;
            if (p[i]->data == ch[i % 2])
            {
                flag = i;
                break;
            }
        }
        if (flag != -1)break;
    }
    
    //按照flag指示输出.
    if (flag != -1)
    {
        while ((count--) - 2 > 0)
        {
            cout << "great-";
        }
        if ((count) == 1)
        {
            cout << "grand";
        }
        cout << ((!flag) ? "parent" : "child") << endl;
    }
    else
    {
        cout << "-" << endl;
    }
}

int main()
{
    int n, t;
    string str;
    char fir, sec;

    while (cin >> n >> t)
    {
        if (!n && !t)
            break;

        BinaryTree bt;

        while (n--)
        {
            cin >> str;
            bt.part(str);
        }

        while (t--)
        {
            cin >> fir >> sec;
            bt.relationship(fir, sec);
        }
    }

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值