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;
}