家族谱

人类学研究对于家族很感兴趣,于是研究人员搜集了一些家族的家谱进行研究。实验中,使用计算机处理家谱。为了实现这个目的,研究人员将家谱转换为文本文件。下面为家谱文本文件的实例:

John
Robert
Frank
Andrew
Nancy
David
家谱文本文件中,每一行包含一个人的名字。第一行中的名字是这个家族最早的祖先。家谱仅包含最早祖先的后代,而他们的丈夫或妻子不出现在家谱中。每个人的子女比父母多缩进2个空格。以上述家谱文本文件为例,John这个家族最早的祖先,他有两个子女Robert和Nancy,Robert有两个子女Frank和Andrew,Nancy只有一个子女David。
在实验中,研究人员还收集了家庭文件,并提取了家谱中有关两个人关系的陈述语句。下面为家谱中关系的陈述语句实例:
John is the parent of Robert
Robert is a sibling of Nancy
David is a descendant of Robert
研究人员需要判断每个陈述语句是真还是假,请编写程序帮助研究人员判断。
输入格式:
对于测试用例中的每句陈述语句,在一行中输出True,如果陈述为真,或False,如果陈述为假。

输入样例:
6 5
John
Robert
Frank
Andrew
Nancy
David
Robert is a child of John
Robert is an ancestor of Andrew
Robert is a sibling of Nancy
Nancy is the parent of Frank
John is a descendant of Andrew

输出样例:
True
True
True
False
False

代码如下:

#include<iostream>
#include<stdio.h>
#include<string>
#include<cstring>
using namespace std;
typedef struct BiTNode
{
    string data;
    int space;//标记该名字有几个缩进
    int parent;//保存此元素父亲的下标
} BiTNode,*BiTree;
BiTNode* CreateTree(int Len)//将家族成员存到数组里
{
    BiTNode* Tree=new BiTNode[Len];
    string name,name1;//家族成员的名字
    getchar();//读换行符
    for(int i=0; i<Len; i++)
    {
        //由于一般的输入会自动忽略空格,故用getline()函数解决
        getline(cin,name);
        int j=0,num=0;//num为空格个数
        while(name[j]==' ')
        {
            num++;
            j++;
        }
        Tree[i].space=num;
        for(; j<name.length(); j++)
            Tree[i].data+=name[j];
        if(i==0)
            Tree[i].parent=-1;
        else
        {
            if(Tree[i].space==Tree[i-1].space)//与上一个结点的父亲相同
                Tree[i].parent=Tree[i-1].parent;
            else if(Tree[i].space > Tree[i-1].space)//是上一个结点的孩子
                Tree[i].parent=i-1;
            else//缩进比上一个结点少,情况比较复杂
            {
                int t=Tree[i-1].parent;
                int m=Tree[t].parent;
                int p=(Tree[i].space-Tree[i-1].space)%2;
                while(p--)
                {
                    if(p==1)
                        break;
                    m=Tree[m].parent;
                }
                Tree[i].parent=m;
            }
        }
    }
    return Tree;
}
int FindPos(string s,int num)//找字符串中第num个单词的第一个字符出现的位置
{
    int i,p=0;//p表示遍历过的空格的个数
    for(i=0; i<s.length(); i++)
    {
        if(s[i]==' ')
            p++;
        if(p==num-1)
            break;
    }
    return i;
}
void Judge(BiTNode *Tree,string &s1,string &s2,string &ss,int L2)//L2为树的长度
{
    int i;
    int pos1,pos2;//表示两个名字出现的位置
    for(i=0; i<L2; i++)
    {
        if(Tree[i].data==s1)
        {
            pos1=i;
        }
        if(Tree[i].data==s2)
        {
            pos2=i;
        }
    }
    if(ss=="child")
    {
        int t=Tree[pos1].parent;
        if(t!=-1)
        {
            if(Tree[t].data==s2)
                cout<<"True"<<endl;
            else
                cout<<"False"<<endl;
        }
        else
        {
            if(Tree[pos1].space-Tree[pos2].space==2)
                cout<<"True"<<endl;
            else
                cout<<"False"<<endl;
        }
    }
    else if(ss=="ancestor")//缩进小的为祖先
    {
        if(Tree[pos1].space<Tree[pos2].space)
            cout<<"True"<<endl;
        else
            cout<<"False"<<endl;
    }
    else if(ss=="sibling")//缩进一样为兄弟
    {
        if(Tree[pos1].space==Tree[pos2].space)
            cout<<"True"<<endl;
        else
            cout<<"False"<<endl;
    }
    else if(ss=="parent")
    {
        int t=Tree[pos2].parent;
        if(t!=-1)
        {
            if(Tree[t].data==s1)
                cout<<"True"<<endl;
            else
                cout<<"False"<<endl;
        }
        else
            cout<<"False"<<endl;
    }
    else if(ss=="descendant")//缩进大的为后代
    {
        if(Tree[pos1].space>Tree[pos2].space)
            cout<<"True"<<endl;
        else
            cout<<"False"<<endl;
    }
}
void InputState(BiTNode *Tree,string &s1,string &s2,string &ss,int L1,int L2)//输入若干陈述句,并提取需要的信息
{
    int i,j;
    int k1=0,k2=0,k3=0;
    string s;//输入的陈述句
    for(i=0; i<L1; i++)
    {
        j=0;
        getline(cin,s);
        while(s[j]!=' ')//提取第一个名字
        {
            s1 += s[j];
            j++;
        }
        j=FindPos(s,6);
        while(s[j]!='\0')//提取第二个名字
        {
            if(s[j]!=' ')
                s2 += s[j];
            j++;
        }
        j=FindPos(s,4)+1;
        while(s[j]!=' ')//提取关系名词
        {
            ss += s[j];
            j++;
        }

        /*Judge*/
        Judge(Tree,s1,s2,ss,L2);

        s1="";
        s2="";
        ss="";
    }
}

int main()
{
    int N,M;
    BiTNode *T;
    cin>>N>>M;
    T=CreateTree(N);
    string str1,str2,str;
    InputState(T,str1,str2,str,M,N);
    //Judge(T,str1,str2,str,N,M);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值