在家谱中查找关系远近

Posted tuoniao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在家谱中查找关系远近相关的知识,希望对你有一定的参考价值。

【问题描述】

同姓氏中国人见面常说的一句话是“我们五百年前可能是一家”。从当前目录下的文件in.txt中读入一家谱,从标准输入读入两个人的名字(两人的名字肯定会在家谱中出现),编程查找判断这两个人相差几辈,若同辈,还要查找两个人共同的最近祖先以及与他(她)们的关系远近。假设输入的家谱中每人最多有两个孩子,例如下图是根据输入形成的一个简单家谱:

技术分享图片

通过该家谱,可以看到wangliang、wangguoping和wangguoan都有两个孩子,wangtian、wangxiang和wangsong有一个孩子,wangguang、wangqinian、wangping和wanglong还没有孩子。若要查找的两个人是wangqinian和wangguoan,从家谱中可以看出两人相差两辈;若要查找的两个人是wangping和wanglong,可以看出两人共同的最近祖先是wangguoan,和两人相差两辈。

【输入形式】

从当前目录下的in.txt中读入家谱。文件中第一行是家谱中有孩子的人数,后面每行内容是每个人的名字和其孩子的名字,名字都由1到20个英文字母构成,各名字间以一个空格分隔,整个家谱中的人员都不会重名;若只有一个孩子,则第二个孩子的名字为NULL;若没有孩子,则不需输入;输入的顺序是按照辈份从高到低依次输入,若孩子A出现在孩子B之前,则A的孩子应在B的孩子之前输入。假设以该形式读入的家谱肯定能够形成类似上图所示的一棵二叉树形式的家谱,家谱中任何两人相差的辈份不会超过100。

从标准输入读入要查找的两个人的名字,两名字间也以一个空格分隔。

【输出形式】

所有信息输出到标准输出上。

若要查找的两人不同辈,则先输出辈份低的名字,再输出辈份高的名字,然后输出相差几辈,都以一个空格分隔;

若两人同辈,按照两人名字从标准输入读取的先后顺序,分行输出两人的最近祖先名字、两人姓名以及相差几辈,各数据间以一个空格分隔。

【样例1输入】

假设当前目录下in.txt文件内容为:

6

wangliang wangguoping wangguoan

wangguoping wangtian wangguang

wangguoan wangxiang wangsong

wangtian wangqinian NULL

wangxiang wangping NULL

wangsong wanglong NULL

从标准输入读取:

wangqinian wangliang

【样例1输出】

wangqinian wangliang 3

【样例1说明】

家谱中输入了六个人名及其孩子的人名,形成了“问题描述”中的家谱,要查找的两人是wangqinian和wangliang,wangliang比wangqinian高3辈。

【样例2输入】

假设当前目录下in.txt文件内容为:

6

wangliang wangguoping wangguoan

wangguoping wangtian wangguang

wangguoan wangxiang wangsong

wangtian wangqinian NULL

wangxiang wangping NULL

wangsong wanglong NULL

从标准输入读取:

wangping wanglong

【样例2输出】

wangguoan wangping 2

wangguoan wanglong 2

【样例2说明】

和样例1同样输入了一家谱,wangping和wanglong共同的最近祖先是wangguoan,该祖先与两人相差两辈。

 

【题解】

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<string.h>
  4 
  5 struct family
  6 {
  7     char parent[25];
  8     char lchild[25];
  9     char rchild[25];
 10 }famList[300];
 11 
 12 struct FT
 13 {
 14     char name[25];
 15     int generation;
 16     struct FT *parent;
 17     struct FT *lchild;
 18     struct FT *rchild;
 19 };
 20 typedef struct FT famTree;
 21 
 22 famTree *root=NULL;
 23 char nochild[]="NULL";
 24 
 25 int read(FILE *fp);
 26 int child(char name[]);
 27 void insertTree(famTree *T,char lchild[],char rchild[]);
 28 famTree *search(famTree *T,char name[]);
 29 
 30 int main()
 31 {
 32     FILE *fp;
 33     int num,i;
 34     char name1[25],name2[25];
 35     famTree *p,*q,*r;
 36     if((fp=fopen("in.txt","r"))==NULL)
 37         exit(-1);
 38 
 39     num=read(fp);
 40 
 41     root=(famTree *)malloc(sizeof(famTree));
 42     strcpy(root->name,famList[0].parent);
 43     root->generation=1;
 44 
 45     r=(famTree *)malloc(sizeof(famTree));
 46     strcpy(r->name,famList[0].lchild);
 47     r->generation=2;
 48     r->parent=root;
 49     r->lchild=r->rchild=NULL;
 50     root->lchild=r;
 51     if(child(famList[0].rchild))
 52     {
 53         r=(famTree *)malloc(sizeof(famTree));
 54         strcpy(r->name,famList[0].rchild);
 55         r->generation=2;
 56         r->parent=root;
 57         r->lchild=r->rchild=NULL;
 58         root->rchild=r;
 59     }
 60 
 61     for(i=1;i<num;i++)
 62     {
 63         r=search(root,famList[i].parent);
 64         insertTree(r,famList[i].lchild,famList[i].rchild);
 65     }
 66 
 67     scanf("%s %s",name1,name2);
 68     p=search(root,name1);
 69     q=search(root,name2);
 70     if(p->generation<q->generation)
 71         printf("%s %s %d
",name2,name1,q->generation-p->generation);
 72     else if(p->generation>q->generation)
 73         printf("%s %s %d
",name1,name2,p->generation-q->generation);
 74     else
 75     {
 76         famTree *pParent,*qParent;
 77         pParent=p;
 78         qParent=q;
 79         while(strcmp(pParent->name,qParent->name)!=0)
 80         {
 81             pParent=pParent->parent;
 82             qParent=qParent->parent;
 83         }
 84         printf("%s %s %d
",pParent->name,name1,p->generation-pParent->generation);
 85         printf("%s %s %d
",qParent->name,name2,q->generation-qParent->generation);
 86     }
 87     return 0;
 88 }
 89 
 90 int read(FILE *fp)
 91 {
 92     int n,i;
 93     fscanf(fp,"%d",&n);
 94     for(i=0;i<n;i++)
 95         fscanf(fp,"%s %s %s",famList[i].parent,famList[i].lchild,famList[i].rchild);
 96     fclose(fp);
 97     return n;
 98 }
 99 int child(char name[])
100 {
101     if(strcmp(name,nochild)==0)
102         return 0;
103     else
104         return 1;
105 }
106 void insertTree(famTree *T,char lchild[],char rchild[])
107 {
108     famTree *p;
109     if(child(lchild))
110     {
111         p=(famTree *)malloc(sizeof(famTree));
112         strcpy(p->name,lchild);
113         p->generation=T->generation+1;
114         p->lchild=p->rchild=NULL;
115         p->parent=T;
116         T->lchild=p;
117     }
118 
119     if(child(rchild))
120     {
121         p=(famTree *)malloc(sizeof(famTree));
122         strcpy(p->name,rchild);
123         p->generation=T->generation+1;
124         p->lchild=p->rchild=NULL;
125         p->parent=T;
126         T->rchild=p;
127     }
128 
129     return;
130 }
131 famTree *search(famTree *T,char name[])
132 {
133     famTree *p,*q;
134     p=T;
135     if(p==NULL)
136         return p;
137     else if(strcmp(p->name,name)==0)
138         return p;
139     else
140     {
141         q=search(p->lchild,name);
142         if(q==NULL)
143             return search(p->rchild,name);
144         else
145             return q;
146     }
147 }

 

以上是关于在家谱中查找关系远近的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P2814 家谱

洛谷P2814 家谱

家谱 要测试数据的在评论里发联系方式

P2814 家谱

并查集——家谱

洛谷P2814 家谱