【问题描述】
同姓氏中国人见面常说的一句话是“我们五百年前可能是一家”。从当前目录下的文件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,该祖先与两人相差两辈。
【评分标准】
该程序要求在家谱中查找判断两人的关系远近,提交程序文件名为find.c。
题解:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int sunxu=0;
struct Node {//建立一个结构体
int biaoji=0;
int time;
char name[20];
Node* lchild;
Node* rchild;
Node* parent;
};
Node* createroot()//初始化根节点
{
Node* newnode = (Node*)malloc(sizeof(Node));
newnode->lchild = NULL;
newnode->rchild = NULL;
newnode->parent = NULL;
newnode->time =1;
newnode->biaoji = 0;
return newnode;
}
Node* root = createroot();
Node* createnode(char* a)//初始化节点
{
Node*newnode= (Node*)malloc(sizeof(Node));
for (int k = 0; k < 20; k++)
{
newnode->name[k] = a[k];
}
newnode->lchild = NULL;
newnode->rchild = NULL;
newnode->parent = NULL;
newnode->time = 0;
newnode->biaoji = 0;
return newnode;
}
int flag = 0;
void insetroot(char*str)//根节点
{
if (flag == 0)
{
for (int k = 0; k < 20; k++)
{
root->name[k] = str[k];
}
root->biaoji = ++sunxu;
}
flag = 1;
}
void bianlishu(Node* node)//先序遍历,调试用
{
if (node == NULL)return;
printf("%s\n",node->name);
bianlishu(node->lchild);
bianlishu(node->rchild);
}
void find(Node* node,char*str,Node *&parent) {//找父节点
if (node != NULL)
{
if (strcmp(node->name,str) == 0)
{
parent=node;
}
else {
find(node->lchild, str,parent);
find(node->rchild, str,parent);
}
}
}
void intsetlchild(char* str, char* str1)//建左树
{
Node* parent=(Node*)malloc(sizeof(Node));
find(root,str,parent);
parent->lchild = createnode(str1);
parent->lchild->biaoji= ++sunxu;
parent->lchild->time = parent->time + 1;
parent->lchild->parent = parent;
}
void intsetrchild(char* str, char* str2)//建右树
{
Node* parent= (Node*)malloc(sizeof(Node));
find(root, str,parent);
parent->rchild = createnode(str2);
parent->rchild->biaoji = ++sunxu;
parent->rchild->time = parent->time + 1;
parent->rchild->parent = parent;
}
int main()
{
int n;
char str[20],str1[100],str2[100],str3[100],str4[100];
FILE* p = fopen("in.txt", "r+");
if (p== NULL)
{
return 0;
}
fscanf(p,"%d",&n);
for (int k = 0; k < n; k++)//建树
{
fscanf(p,"%s %s %s", str, str1, str2);
//printf("%s %s %s\n", str, str1, str2);
insetroot(str);
intsetlchild(str, str1);
intsetrchild(str, str2);
}
fclose(p);
//bianlishu(root);//测试用
scanf("%s %s",str3,str4);
Node* p1=(Node*)malloc(sizeof(Node));
find(root, str3,p1);
Node* p2= (Node*)malloc(sizeof(Node));
find(root, str4,p2);
if (p1->time != p2->time)//根据条件输出
{
if (p1->time > p2->time)
{
printf("%s %s %d\n", p1->name, p2->name,p1->time-p2->time);
}
else
{
printf("%s %s %d\n", p2->name, p1->name, p2->time - p1->time);
}
}
if (p1->time == p2->time)
{
Node *p3, *p4;
p3 = p1;
p4 = p2;
while (p1->parent != p2->parent)
{
p1 = p1->parent;
p2 = p2->parent;
}
if (p3->biaoji<p4->biaoji)
{
printf("%s %s %d\n", p1->parent->name,p3->name,p3->time-p1->parent->time);
printf("%s %s %d", p1->parent->name, p4->name, p4->time - p1->parent->time);
}
else
{
printf("%s %s %d\n", p1->parent->name, p3->name, p4->time - p1->parent->time);
printf("%s %s %d", p1->parent->name, p4->name, p3->time - p1->parent->time);
}
}
return 0;
}