在家谱中查找关系远近
在家谱中查找关系远近
【问题描述】
同姓氏中国人见面常说的一句话是“我们五百年前可能是一家”。从当前目录下的文件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。
思路
- 本题的目标是查询辈分差或者找到最小共同父辈,因此可以使用树的结构处理,每个节点通过存储树的层次来表示辈分,并为每个节点添加一个指针,记录下每个点的父节点,以便后续查找父节点。
- 个人认为本题的难点在于创建这个树的结构,后续查询以及处理都是较为简单的。
代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 1000
#define LEN_NAME 30typedef struct Fnode* FNode;
int pos = 1;
struct Fnode {char Name[LEN_NAME]; //人名FNode Parent, Lchild, Rchild; //父节点及子节点int Degress; //辈分,逆排
};FNode init(FNode P, char name[])
{if (!strcmp(name, "NULL"))return NULL;FNode n = (FNode)malloc(sizeof(struct Fnode));n->Lchild = n->Rchild = NULL;n->Parent = P;n->Degress = P ? P->Degress + 1 : 1; //辈分最大的记为1strcpy(n->Name, name);return n;
}void getName(char str[], char name[3][LEN_NAME])
{int i = 0, j = 0, k = 0;char c = str[i++];while (c != '\n' && c != '\0') {if (c == ' ') { //遇到空格重置,记录新的人名j++;k = 0;} else name[j][k++] = c;c = str[i++];}
}FNode search(FNode F, char name[])
{if (!F) return NULL; //空节点else if(!strcmp(name, F->Name)) return F; //已经查找到该名字对应的节点else return search(F->Lchild, name) ? search(F->Lchild, name) : search(F->Rchild, name); //如果当前节点不符合,递归查询其子节点
}FNode creatTree(FNode F, char data[N][N])
{FNode nodes[N];int pos_nodes = 0, i;nodes[pos_nodes++] = F; //按层创建树,先将根节点存入for (i = 0; i < pos_nodes; i++) {char name[3][LEN_NAME] = { '\0' };getName(data[pos], name);if (!strcmp(nodes[i]->Name, name[0])) { //解析到当前节点的信息,则为其创建子节点FNode l = init(nodes[i], name[1]), r = init(nodes[i], name[2]);nodes[i]->Lchild = l;nodes[i]->Rchild = r;if (l) nodes[pos_nodes++] = l;if (r) nodes[pos_nodes++] = r;pos++;}}return F;
}void print(FNode F1, FNode F2)
{FNode f1 = F1, f2 = F2;if (f1->Degress > f2->Degress) //两人辈分不同printf("%s %s %d", f1->Name, f2->Name, f1->Degress - f2->Degress);else if(f1->Degress < f2->Degress)printf("%s %s %d", f2->Name, f1->Name, f2->Degress - f1->Degress);else { //两人辈分相同,查询其最小共同父代while (strcmp(f1->Name, f2->Name)) {f1 = f1->Parent;f2 = f2->Parent;}printf("%s %s %d\n", f2->Name, F1->Name, F1->Degress - f2->Degress);printf("%s %s %d", f2->Name, F2->Name, F2->Degress - f2->Degress);}
}int main()
{int n = 0;char data[N][N] = { '\0' }, name[3][LEN_NAME] = { '\0' }, names[2][LEN_NAME];FILE* fp = fopen("in.txt", "r");while (!feof(fp))fgets(data[n++], 3 * LEN_NAME, fp); //读取文本内容,含'\n'fclose(fp);getName(data[1], name); //先获得辈分最大的人的姓名,创建根节点FNode F = init(NULL, name[0]);creatTree(F, data); //创建整个树scanf("%s %s", names[0], names[1]);FNode F1 = search(F,names[0]), F2 = search(F, names[1]); //找到两个人名对应的节点print(F1, F2);return 0;
}
在家谱中查找关系远近相关推荐
- 数据库-ADONET-在数据集DataSet中使用关系对象DataRelation处理关系
处理关系数据 数据库中,表很少是独立结构的,大部分数据库都包含相互关联的表. 在构建应用程序时,会遇到--显示或者通过程序设计访问数据库中相关表的数据的情况. 用户会希望,能通过在不同的表之间定位,来 ...
- 文本编辑器中查找对话框及功能实现
文章目录 1 查找对话框界面实现 2 查找对话框的功能实现 1 查找对话框界面实现 查找对话框需求分析: 可复用软件部分. 查找文本框中的指定字符串. 能够指定查找方向. 支持大小写敏感查找. 附加需 ...
- 从集合中查找最值得方法——max(),min(),nlargest(),nsmallest()
从集合中查找最值得方法有很多,常用的方法有max(),min(),nlargest(),nsmallest()等. 一.max()和min() 1.1 入门用法 直接使用max(),min(),返回可 ...
- 在Python中查找子字符串索引的5种方法
在Python中查找字符串中子字符串索引的5种方法 (5 Ways to Find the Index of a Substring in Strings in Python) str.find() ...
- oracle中dbms_如何在DBMS中找到关系的最高范式?
oracle中dbms To find the highest normal form of a relation, you have to first understand the basics o ...
- Python使用Apriori算法查找关系密切的演员组合
Apriori算法基本概念: 关联规则:可以表示为一个蕴含式R:X==>Y,其中X&Y为空集.关联规则的含义是,如果X发生,那么Y很可能也会发生. 关联分析或者关联规则学习:从大规模数据 ...
- ubuntu中手动编译源码安装Xorg-server过程中依赖关系的解决
ubuntu中手动编译源码安装Xorg-server过程中依赖关系的解决 在linux系统中手动编译源码安装软件包的过程是非常痛苦的,然而这一个多星期以来我是强忍住脾气体验了一把,虽然面对慢的令人发指 ...
- 如何在Java项目中查找未使用/无效的代码
本文翻译自:How to find unused/dead code in java projects What tools do you use to find unused/dead code i ...
- idea中查找的快捷键
idea中查找的快捷键 下面是查找IntelliJ IDEA编译后的class文件路径的具体操作步骤. 1.IDEA左上角打开File-Project Structure,或者直接按默认快捷键Ctrl ...
最新文章
- Hazelcast介绍与使用
- if vue 跳出_vue使用v-if v-show 页面闪烁
- (转)自定义EndNote的输出样式(output style)
- 线程----BlockingQueue (转)
- Scala Array sum recursive call
- Android 的滑动分析以及各种实现
- 用SSAS将多个FLV和MP3合成一个FLV文件
- 入门第十课 Python语句的编写之while
- 【笔试/面试】—— 数组中第二大的数
- 程序猿学习中华古诗词路径
- 如何用计算机制作pop海报,怎么用ps制作pop海报_ps制作pop字体
- Thymeleaf数据回显
- 加速度、陀螺仪传感器工作原理
- 电脑测试,模拟微信内置浏览器Firefox/chrome
- JavaWeb中外部引入的js中涉及到location.href的页面跳转/jsp页面的外部js文件引入
- 黄金圈理论和知识体系
- 交通灯控制器的verilog实现
- lms消噪声matlab,关于LMS去噪声的仿真
- 同济大学计算机复试刷人多吗,同济大学土木工程专业考研复试要刷掉多少人
- 微信分享网页链接自定义标题,图片,文字描述