人类族谱管理系统设计报告.docx
- 文档编号:25174010
- 上传时间:2023-06-05
- 格式:DOCX
- 页数:30
- 大小:1.42MB
人类族谱管理系统设计报告.docx
《人类族谱管理系统设计报告.docx》由会员分享,可在线阅读,更多相关《人类族谱管理系统设计报告.docx(30页珍藏版)》请在冰豆网上搜索。
人类族谱管理系统设计报告
软件学院
综合训练工程报告书
课程名称数据构造
工程名称人类家谱管理系统
专业班级软件13-3班
组别第五组
成员伟竹王雨柔何惠民
任课教师宁
1.设计时间………………………………………………………………1
2.设计任务………………………………………………………………1
3.设计容………………………………………………………………1
3.1问题分析…………………………………………………………….1
3.2程序设计……………………………………………………………3
3.3测试与分析………………………………………………………..10
3.3.1测试………………………………………………………..……10
3.3.2分析………………………………………………………..……14
3.4代码………………………………………………………………..14
4.总结与展望………………………………………………………….21
5.参考文献…………………………………………………………….22
1设计时间
2014年12月16日——2015年1月6日
2设计任务
树形构造是一种非常重要的非线性构造,它用于描述数据元素之间的层次关系,人类家谱是树形构造的典型表达,通过此项训练让学生掌握树形构造的知识;使学生重点掌握树与二叉树的转换,二叉树的存储和遍历;此项训练要求构造一棵家谱树,并完成任意成员的查找。
3设计容
3.1问题分析
1.程序所能到达的功能,见功能模块图〔图3-1〕。
〔1〕输入家族始祖信息,初始化〔或创立〕一个家族族谱树。
〔2〕输入要添加人信息,插入新的家族成员。
〔3〕输入要查找人,对家族成员进展查找。
〔4〕输入要修改人,修改某一个家族成员信息。
2.输入的形式和输出的形式。
输入和输出的可以是中文也可以是英文,变量名为char类型,且最多不得多余20字符,对于某一个人所处代数为数字,变量名为int类型,对输入输出的性别,本设计要M或F表示,故必须是英文,为char类型的变量。
3.存储构造设计思想。
本工程设计采用孩子兄弟链表〔二叉链表〕方式存储信息,包含一个data域和两个指针域,其中data域又为一个构造体类型,存储某一个人的信息,而对于指针域,一个为child域,指向此人的孩子,另一个为brother域,指向此人的兄弟姐妹,形成如下存储构造,见图3-2。
4.测试数据。
首先,创立一个家谱,输入始祖的及性别,然后根据菜单要求输入要选择的步骤,本次测试以三代人的家谱为例,输入三代人的及性别,三代人各查找一次,修改某一代人〔或性别〕后,查找修改人信息,以验证本程序是否正确,最后退出族谱管理系统。
当家谱中成员存在时,显示初始化、添加、修改成功等信息。
当家谱中不存在此成员时,系统提示信息有误,要求重新输入所要添加、查找或修改人的信息。
图3-1功能模块图
图3-2存储构造图
3.2程序设计
1.本程序中用到的所有抽象数据类型的定义及实现。
〔1〕定义一个data存储构造,存放个人信息。
typedefstructnode
{
charname[MAX];//
charsex;//性别
intgeneration;//代
}node;
〔2〕此处采用孩子兄弟链表法,定义一个构造体存放各代人信息。
typedefstructtreenode
{
structnodel;//家谱中直系家属
structtreenode*brother;//用来指向兄弟
structtreenode*child;//用来指向孩子
}treenode;
〔3〕定义一个指针变量,为treenode类型,指向各代人信息。
treenode*root;//root是指向构造体treenode的指针
〔4〕主要函数列表及说明,见表3-1。
表3-1主要函数列表及说明
函数名及其类型
函数功能
参数及其类型
参数功能
InitTree
void型,无返回值
创立一个家族族谱
charb[MAX],c
inta
数组参数b[MAX]存放;参数c代表性别;参数a代表此人是第几代人
Add
void型,无返回值
添加家谱新成员
inta
Treenode*m,*n
Treenode*t
参数a接收搜索到的代数;m,n,t为三个treenode类型的指针变量,将搜索到的个人信息赋给m,n,t
Search
void型,无返回值
查找家谱成员信息
chard[MAX]
treenode*n
数组参数d[MAX]用于存放;n为treenode类型的指针变量,将搜索到的个人信息赋给n
Change
void型,无返回值
修改家谱成员信息
chara[MAX],c
charr[MAX]
treenode*n
inti
数组参数a[MAX]存放要修改人的;数组参数r[MAX]存放修改后的;c代表修改的性别;n为treenode类型的指针变量,将搜索到的个人信息赋给n
2.主程序的流程图及函数的调用关系图。
(1)主函数流程图,见图3-3。
图3-3主函数流程图
(2)创立函数流程图,见图3-4。
图3-4创立函数流程图
(3)查找函数流程图,见图3-5。
图3-5查找函数流程图
(4)添加函数流程图,见图3-6。
图3-6添加函数流程图
(5)修改函数流程图,见图3-7。
图3-7修改函数流程图
(6)函数关系调用图,见图3-8。
图3-8函数关系调用图
3.主要函数伪码算法。
〔1〕创立函数伪码。
begin
free(root)
root(treenode*)malloc(sizeof(treenode))
print“输入始祖及性别:
〞
inputb,c
1=>a
NULL=>root->child
NULL=>root->brother
children(root,b,c,a)
print“家谱初始化成功!
〞
end
(2)添加函数伪码。
begin
print“请输入要添加子女的上一代人:
〞
inputd
search(root,d)=>n
generation(root,d)=>a
while(n==NULL)
{
print“此人不存在,请重新输入!
〞
inputd
search(root,d)
}
if(n->child==NULL)
{
print“输入孩子的及性别:
〞
inputb,c
a+1=>a
search(root,b)=>m
if(m!
=NULL)
print“出现重名,添加失败!
〞
else
{
(treenode*)malloc(sizeof(treenode))=>n->child
NULL=>n->child->brother
NULL=>n->child->child
children(n->child,b,c,a)
print“家谱成员添加成功!
〞
}
else
{
n->child=>n
while(n->brother!
=NULL)
{
n->brother=>n
print“输入孩子的及性别:
〞
inputb,c
a+1=>a
search(root,b)=>m
if(m!
=NULL)
print“出现重名,添加失败!
〞
else
{
(treenode*)malloc(sizeof(treenode))=>t
children(t,b,c,a)
NULL=>t->brother
NULL=>t->child
t=>n->brother
print“家谱成员添加成功!
〞
}
}
}
end
〔3〕查找函数伪码。
begin
print“输入要查找人:
〞
inputd
search(root,d)=>n
while(n==NULL)
{
print“此人不存在,请重新输入:
〞
inputd
search(root,d)=>n
}
output(n)
end
(4)修改函数伪码。
begin
print“输入要修改人的:
〞
inputa
search(root,a)=>n
while(n==NULL)
{
print“此人不存在,请重新输入:
〞
inputa
search(root,a)=>n
}
inputr,c
0=>i
while(i { r[i]=>r->l.name[i] i+1=>i } c=>n->l.sex print“家谱成员信息修改成功! 〞 end 3.3测试与分析 3.3.1测试 1.开场 进入菜单项选择择界面 2.运行过程 〔1〕当输入信息正确时 初始化〔创立〕一个家谱 添加家族成员 查找家族成员信息 修改家族成员信息 查找修改的成员信息 (2)当输入错误信息时,系统做出提示,请求重新输入成员信息 添加输入错误信息时 查找输入错误信息时 修改输入错误信息时 查找修改人原名,系统提示不存在 3.完毕 退出系统 3.3.2分析 从算法的设计、效率以及实用性上来说: 总的来讲,设计不是很严谨,实际生活中的人类家族族谱是有配偶信息的,而且个人信息中不仅包含、性别、双亲、子女,还应该有出生日期、死亡日期、籍贯等信息的。 但是在本程序中,大局部信息没有记录族谱中,这是本设计的缺陷所在,故实用性并不高。 但是,本设计也有其优点所在,就是有错误信息提示,不管是在添加成员信息,还是查找、修改成员信息时,当输入不存在时,系统会给出错误信息提示,要求重新输入此人。 另外,本程序设计了指针搜索函数,便于搜索孩子和双亲信息 从改良设想上: 本程序设计的设计思想是很简单的,为了能够将家族成员信息记录全面,在存放个人信息的构造体中添加一局部信息,比方此人的出生日期、死亡日期、籍贯等,在存放各代人信息时,添加一个构造体类型的变量,用于存放配偶的信息,以便实现对此人配偶信息的存储,提高实用性。 3.4代码 #include #include #include #include #defineMAX10 typedefstructnode//定义data存储构造,存放个人信息 { charname[MAX];// charsex;//性别 intgeneration;//代 }node; typedefstructtreenode//创立构造体 { structnodel;//家谱中直系家属 structtreenode*brother;//用来指向兄弟 structtreenode*child;//用来指向孩子 }treenode; treenode*root;//root是指向构造体treenode的指针 treenode*search(treenode*p,charch[])//搜索指针函数,搜索需要修改和获得的结点,输入头指针, { treenode*q; if(p==NULL)returnNULL;//没有家谱,头指针下为空 if(strcmpi(p->l.name,ch)==0)//比拟,看是否重名或是否存在 returnp;//家谱不为空,头指针下有这个人 if(p->brother) { q=search(p->brother,ch);//在兄弟中找 if(q) returnq;//找到 } if(p->child) { q=search(p->child,ch);//在孩子中找 if(q! =NULL) returnq;//找到 } returnNULL;//没有找到 } treenode*parent(treenode*p,treenode*q,int*flag)//搜索双亲的指针函数,通过parent函数得到双亲结点。 用flag标志,-1为左孩子,1为右孩子 { if(p==NULL)returnNULL;//没有家谱,头指针下为空 if(p->child==NULL) { flag=0; returnNULL; } else { if(p->brother==q) { *flag=1; returnp; } else { if(p->child==q) { *flag=-1; returnp; } else { if(p->brother! =NULL) { parent(p->brother,q,*&flag); } if(p->child! =NULL) { parent(p->child,q,*&flag); } } } } returnp; } intgeneration(treenode*p,charch[])//获得搜索到的成员的代的返回值 { treenode*q; if(p==NULL)return0; if(strcmpi(p->l.name,ch)==0)//比拟,看是否重名或是否存在 returnp->l.generation;//家谱不为空,头指针下有这个人 if(p->brother) { q=search(p->brother,ch);//在兄弟中找 if(q) returnq->l.generation;//找到 } if(p->child) { q=search(p->child,ch);//在孩子中找 if(q! =NULL) returnq->l.generation;//找到 } return0; } voidchildren(treenode*p,charb[],charc,intd)//建立家谱孩子结点,创立结点并对l赋值保存 { inti; for(i=0;i p->l.name[i]=b[i]; p->l.sex=c; p->l.generation=d; } voidoutput(treenode*n)//搜索到数据的输出 { treenode*t=NULL; printf("此人: %s性别%c为第%d代\n",n->l.name,n->l.sex,n->l.generation); printf("\n"); printf("此人的子女: ");//子女输出 if(n->child==NULL) { printf("此人无子女! "); } else { if(n->child->brother==NULL) { printf(": %s性别: %c\t",n->child->l.name,n->child->l.sex); } else { printf(": %s性别: %c\t",n->child->l.name,n->child->l.sex); t=n->child->brother; while(t! =NULL) { printf(": %s性别: %c\t",t->l.name,t->l.sex); t=t->brother; } } } printf("\n"); printf("此人的同辈成员: ");//同辈输出 if(n->brother==NULL) { printf("此人无同辈成员! "); } else { if(n->brother->brother==NULL) { printf(": %s性别: %c\t",n->brother->l.name,n->brother->l.sex); } else { printf(": %s性别: %c\t",n->brother->l.name,n->brother->l.sex); t=n->brother->brother; while(t! =NULL) { printf(": %s性别: %c\t",t->l.name,t->l.sex); t=t->brother; } } } } voidInitTree()//初始化〔创立〕 { charb[MAX],c; inta; printf("请输入始祖的性别: "); free(root);//释放root〔ft〕空间 root=(treenode*)malloc(sizeof(treenode));//创立一个treenode构造体大小的空间 //然后强制转换为treenode*类型的指针然后赋值给root scanf("%s%c",&b,&c);//输入,性别 a=1; root->child=NULL;//清空左右孩子 root->brother=NULL; children(root,b,c,a);//存入构造 printf("家谱初始化成功! \n"); } voidAdd()//添加 { treenode*n,*m,*t=NULL; charb[MAX],c,d[MAX]; inta; printf("请输入要添加子女的上一辈的: "); scanf("%s",&d); n=search(root,d); a=generation(root,d); while(n==NULL)//判断是否有重名 { printf("此人不在家谱,请重新输入: "); scanf("%s",&d); n=search(root,d); } if(n->child==NULL)//孩子信息添加 { printf("孩子与性别输入: "); scanf("%s%c",&b,&c); a++; m=search(root,b); if(m! =NULL) { printf("出现重名,添加失败! \n"); } else { n->child=(treenode*)malloc(sizeof(treenode)); n->child->brother=NULL; n->child->child=NULL; children(n->child,b,c,a); printf("添加成功! \n"); } } else { n=n->child; while(n->brother! =NULL)//添加另一个孩子 n=n->brother; printf("孩子与性别输入: "); scanf("%s%c",&b,&c); a++; m=search(root,b); if(m! =NULL) printf("出现重名,添加失败! \n"); else { t=(treenode*)malloc(sizeof(treenode)); children(t,b,c,a); t->brother=NULL; t->child=NULL; n->brother=t; printf("添加成功! \n"); } } } voidSearch()//查找 { treenode*n; chard[MAX]; printf("输入,查找相关信息: "); scanf("%s",&d); n=search(root,d); while(n==NULL) { printf("此人不存在,请再次输入: "); scanf("%s",&d); n=search(root,d); } output(n); printf("\n"); } voidChange()//修改 { chara[MAX],r[MAX],c; treenode*n; inti; printf("请输入要修改人的: "); scanf("%s",&a); n=search(root,a); while(n==NULL) { printf("此人不存在,请重新输入: "); scanf("%s",&a); n=search(root,a); } printf("此人存在,请输入新信息: "); scanf("%s%c",&r,&c); for(i=0;i n->l.name[i]=r[i]; n->l.sex=c; printf("修改成功! \n"); } intmain() { intchoice; for(;;) { system("pause"); printf("请选择对家谱的操作: \n"); printf("1.初始化〔创立〕\n"); printf("2.添加\n"); printf("3.查找\n"); printf("4.修改\n"); printf("5.退出\n"); scanf("%d",&choice); switch(choice) { case1: InitTree();break;//初始化 case2: Add();break;//添加 case3: Search();break;//查找 case4: Change();break;//修改 case5: exit(0);break;//退出 } } return0; } 4总结与展望 在这次工程设计过程中遇到过一些问题,但经过不懈努力,解决了局部,还有的现在不能解决,留待日后思考和解决。 另外程序还有一些缺陷存在,只能满足题目要求,但实用性并不高,对于家谱中的成员信息,只是记录了和性别,但是在实际生活中,还应该包括出生日期、死亡日期、配偶、籍贯等信息。 但经过后期努力尽量将设计的家谱管理系统更具有实用性。 另外在本次工程设计过程中总结了不少经历,在编写之前,做整体规划和详细设计很重要,只有思路清晰,设计合理可行,编码才有可能有的放矢,才能更加有效的完成任务;写程序时必须要细心,不能输错一个字符、标点;在修改时要有耐心,编译出错后必须诸错误去改正,决不能心浮气躁,否那么还会出现新的错误。 本次工程设计,对我来说可以算是一次挑战,因为在理论学习中没有好好的掌握,现在要独立完成一个较复杂的程序编写,确实有一点困难。 但我对于难度一向是以积极迎战的态度来面对,认真积极努力完成这次工程设计任务。 对我来说这是一次很好的时机,同时我也很好的把握了这次时机,认
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 人类 族谱 管理 系统 设计 报告