欢迎来到冰点文库! | 帮助中心 分享价值,成长自我!
冰点文库
全部分类
  • 临时分类>
  • IT计算机>
  • 经管营销>
  • 医药卫生>
  • 自然科学>
  • 农林牧渔>
  • 人文社科>
  • 工程科技>
  • PPT模板>
  • 求职职场>
  • 解决方案>
  • 总结汇报>
  • ImageVerifierCode 换一换
    首页 冰点文库 > 资源分类 > DOCX文档下载
    分享到微信 分享到微博 分享到QQ空间

    家谱管理系统设计实现分析.docx

    • 资源ID:16759241       资源大小:216.83KB        全文页数:29页
    • 资源格式: DOCX        下载积分:5金币
    快捷下载 游客一键下载
    账号登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录 QQ登录
    二维码
    微信扫一扫登录
    下载资源需要5金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP,免费下载
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    家谱管理系统设计实现分析.docx

    1、家谱管理系统设计实现分析课程设计报告课程名称 数据结构 课题名称 排序综合 专 业 班 级 学 号 姓 名 联系方式 指导教师 20 11 年V2 月21 日1.问题陈述 32 设计方法阐述 32.1总体规划 32.2 功能构想 42.2.1 增加成员 42.2.2修改成员资料 52.2.3 删除成员 62.2.4打开家谱 72.2.5新建家谱 82.2.6保存家谱 102.2.7查看某代信息 112.2.8按姓名查找 122.2.9按生日查找 122.2.10查看成员关系 132.2.11 按出生日期排序 142.3板块整合 152.4调试分析 193.总结 194.测试结果 201.问题陈

    2、述家谱用于记录某家族历代家族成员的情况与关系。现编制一个家谱资料管理软件,实现对一个家族所有的资料进行收集整理。支持对家谱的存储、更新、查询、统计等操作。并 用计算机永久储存家族数据,方便随时调用。2.设计方法阐述2.1总体规划在动手编制程序之前,先要做好程序的规划,包括程序储存数据所用的结构,数据类型等等,只有确定了数据类型和数据结构, 才能在此基础上进行各种算法的设计和程序的编写。首先是考虑数据类型。在家谱中,家族成员是最基本的组成部分,对于家族管理中,已经不能再进行细分了,所以选定家族成员作为数据的基本类型,并在 程序中定义COperatio nFamilytree 类。其中 COper

    3、atio nFamilytree 类的各种属性可以根据需要进行添加或删除,从日常生活应用的角度出发,制定了 COperatio nFamilytree 类中包含了一下属性:char nameMAX_CHARNUM; / 姓名出生日期基本资料健在否死亡日期返回pNode孩子数/返回pNode在其兄弟中的排行类的某些属性中用数字代替了某些不会改变的(1为是,0为否)。在设置日期上,为方便以后的计算与比较, 也将日期用整型数字表示 19990505表示1999年5月5日,这种表示方法只需在输入和输出上作少许的运算便可方便地与日期进行转换。 在家族关系的表示上,并没有用相关家属的姓名作为储存数据,而仅

    4、仅是存储了各关系亲属的 ID,方便日后作为指针指示调用相对应的家族成员。 其中在属性pNode上,其表示的是下一个同父母的弟或妹ID,也就是说,当某家族成员有若干个子女,其 pNode仅指向第一个孩子,其余的孩子如何表示呢?可以通过第一个孩子的 pNode指示,如此类推,直到孩子的 pNode =0为止。有多少孩子就表示多少,实现这样就可以避免需在程序设计时预定父母可以拥有的孩子数, 了动态的储存数据。在选择数据结构方面,从直观来说,选择树型结构通过链表来连接数据无疑是最直观易懂的,我在一开始构思的时候也是从树型结构去想的, 但当构思到如何存储和提取数据是,便发现了问题。毫无疑问,用指针来处理

    5、数据的确是方便直观,但当我要储存数据是, 便发现把指针储存进去是没有作用的, 因为当我们下一次读取数据的时候, 数据内存地址已经不同了,不在是我们上次存储数据时的地址, 也就是说指针这时已经是没有作用了。 要解决这样的问题,我们必须要在存储数据之前, 先家族树序列化,用数组 (或者其他可以用数字表示关系的方法)来存储,并且,再下一次读取数据时,再把数据按照序列号重新组成一个家族树,过程比较繁复,而且实现起来也不容易。所以我便考虑直接用数组来存储数据, 即使是在内存中也用数组来处理数据间的联系。 运用顺序表这个结构虽然不是那么直观, 但在查效率高,而且在内存中的数据可以直接读入到文件不需要进行转

    6、换。所以在衡量的各个方面之后,我找数据时的算法设计比较简单容易实现, 中,文件中的数据也可以直接读入内存, 决定用数组来处理数据间的联系。2.2功能构想构想好总体规划之后,便开始设计程序中需要用到的各个功能函数,初步构想是要先 实现最基本的几项功能,其中数据操作的有:增加成员,修改成员资料,删除成员;数据存 取的有:打开家谱,新建家谱,保存家谱,另存家谱;数据查询的有:查看某代信息,按姓 名查找,按生日查找,查看成员关系,按出生日期排序等等。221增加成员这项功能做得不够理想,在规划时没有把成员以配偶的形式增加,而只能以子女的形式增加。对应的函数代码如下:void COperati onF a

    7、milytree:Add(Pers on pare nt, Pers on addNode)/本函数把addNode结点加入到其父结点 pare nt下addNode-child=addNode-sibling=0; /把欲加入的结点所有指针域置空addNode-pare nt=pare nt; / 因 addNode 欲加为 pare nt 的孩子,故addNode结点的父指针域应指向 pare nt修改成员这项功能实现起来比较简单, 找到要修改成员的名字, 再输入新修改的值, 整个函数没有什么需要运用算法的地方, 但如果想真正写好这个函数,则需要考虑相当多的细节,譬如各个输入项目的错误处理

    8、等等,要非常全面地考虑各项细节。函数代码如下:void CFamilytreeDlg:O nM odify()II TODO: Add your comma nd han dler code hereif(operFamilytree.GetRoot()=0)return;CModifylnfoDlg dlg;HTREEITEM hltem;hItem=m_peTree.GetSelectedItem();dlg.m_ newn ame=m_peTree.GetltemText(hltem);Pers on on eself=0;char old nameMAX_CHARNUM;strcpy(

    9、old name,dlg.m _newn ame);operFamilytree.Fi nd(operFamilytree.GetRoot(),o neself,old name);if(dlg.DoModal()=IDCANCEL)return;UpdateData(FALSE);Pers on n ewValue=new Pers onN ode;strcpy(newValue-info.name,dlg.m_newname); II 判断家谱中是否已有用户给定的新名字if(strcmp( newValue-info.n ame,old name)=O); /用户不修改姓名elsePers

    10、 on p=0;operFamilytree.Fi nd(operFamilytree.GetRoot(),p, newValue-i nfo. name);/查找家谱中有没有此人if(p!=O)AfxMessageBox(家谱中已有此人!);delete n ewValue;return;strcpy( newValue-i nfo.addr,dlg.m _n ewaddr);n ewValue-i nfo.marry=dlg.m_marry;n ewValue-i nfo.live=dlg.m_live;n ewValue-i nfo.birthday.day=dlg.m_birthday

    11、_day;n ewValue-i nfo.birthday.m on th=dlg.m_birthday_mo nth;n ewValue-in fo.birthday.year=dlg.m_birthday_year;if(!newValue-info.live) / 如若过世,则应有死亡日期n ewValue-in fo.deathday.day=dlg.m_deathday_day;n ewValue-i nfo.deathday.m on th=dlg.m_deathday_mo nth;n ewValue-in fo.deathday.year=dlg.m_deathday_year

    12、;if(!operFamilytree.lsDateValid( newValue-i nfo.deathday)AfxMessageBox(此人信息中死亡日期不合实际 );delete n ewValue;return;if(operFamilytree.CompareDate( newValue-i nfo.deathday, newValue-i nfo.bi rthday)=-1)AfxMessageBox(此人死亡日期不可能比其出生日期早 r);return;operFamilytree.Modify(o neself, newValue);RefreshTree();Refresh

    13、List();IsFamilytreeModified=true; / 置家谱修改标记为真delete n ewValue;2.2.3删除成员用数组来储存数据,最麻烦的就是删除数组元素了,在这个程序中,删除数组不但意味着要重新排列各成员, 还要重新更新各成员的关系, 所以我个人认为在这个程序中, 删除成员函数可以说是一个难点。 通过分析,发现删除成员的情况就只有两种, 只要针对这两种情况处理好删除,就可以完成成员删除这个功能。1,删除的成员是出于家族中最底层的, 也就是删除该成员不会牵连其他成员, 但这也 需要处理好其父母的孩子数。2,删除的成员还有子孙,则需要连带所有子孙都要删除出家谱。再是

    14、简单删除了一个人,而是若干个,通过递归调用,可以统计出需要删除的数目删除函数的相关代码如下:第一个孩子位置for(;p-sibli ng!=rootNode;p=p-sibli ng)删除以 rootNode-child/删除rootNode 结点。如PostOrderTraverse(rootNode-child,DestroyNode); 为根结点的所有结点if(rootNode=T)果rootNode为根结点,则删除根结点 TDestroyNode(T);elseDestroyNode(rootNode);224打开家谱打开家谱函数的相关代码如下:int COperati onF ami

    15、lytree:ReadNode(FILE *fp, Pers on &T,char* pare ntn ame) /本函数从文件fp中读取信息到结点 T中,并读取结点的父亲名字到字符数组 parentname中/分别读取结点值,为:姓名,出生日期(年,月,日),婚否,地址,健在否,(如过世,还有死亡日 期)fscan f(fp,%s%d%d%d%d%s%d,T-i nfo.n ame,&T-i nfo.birthday.year,&T-i nfo.birthday.mo nth,&T-i nfo.birthday.day, &T-i nfo.marry,T-i nfo.addr, &T-i n

    16、fo.l ive);if(T-in fo.live=0)fsca nf(fp,%d%d%d,& T-i nfo.deathday.year, &T-i nfo.deathday.mo nth,&T-in fo.deathday.day);fscan f(fp,%s,pare ntn ame);if(!lsDateValid(T-info.birthday) / 出生日期合法性检查return FILE_DATA_NOT_PRACTICAL;if(T-info.live=0) /若过世,死亡日期合法性检查 if (CompareDate(T-in fo.birthday,T-in fo.deat

    17、hday)!=-1)return FILE_DATA_NOT_PRACTICAL;if(!lsDateValid(T-i nfo.deathday)return FILE_DATA_NOT_PRACTICAL;return OK;2.2.5新建家谱新建家谱函数的相关代码如下 :void COperatio nF amilytree:NewFamilytree()/本函数新建一空家谱DestroyFamilytree(); / 删除原有家谱T=0;int COperati onF amilytree:CreateFamilytree(CStri ng file name) /本函数建立一新家谱D

    18、estroyFamilytree();/建立一新豕谱之前,清空原有家谱FILE* fp;if(fp=fope n(file name,r)=0)/打开文件file namereturn READ_FILE_ERROR;T=new Pers onN ode;/定义根结点if(!T)return NOT_ENOUGH_MEMORY;T-child=0;T-sibli ng=0;T-pare nt=O;Pers on pare ntT, temp;/定义两个临时结点char pare ntn ameMAX_CHARNUM;/定义一个临时字符串数组/读取根结点值,(姓名,出生日期(年,月,日),婚否,

    19、地址,健在否,(如过世,还有死 亡日期)int result;result=ReadNode(fp,T,pare ntn ame);if(result=FILE_DATA_NOT_PRACTICAL)delete T; /若不合法,删除申请的堆空间T=0;return result;/根结点名字与其父亲名字相/申请一结点/申请失败/释放申请空间if(strcmp(T-i nfo. name,pare ntn ame)=0) 同,说明为空树delete T;T=0;return PEDIGREE_EMPTY;temp=new Pers onN ode;if(!temp)DestroyFamily

    20、tree();return NOT_ENOUGH_MEMORY; result=ReadNode(fp,temp,pare ntn ame);while(strcmp(temp-i nfo. name,pare ntn ame)&strcmp(temp-i nfo.n ame,e nd) /读取信息结束的条件是两个人的名字同为 endif(result=FILE_DATA_NOT_PRACTICAL) / 若数据不合法,释放已申请空间,然后返回delete temp;DestroyFamilytree();return result;pare ntT=O;Find(T,parentT,pare

    21、ntname); / 找至U parentname 所在结点pare ntTif(parentT) / 女口果 parentT 存在,说明 parentname 在家谱中/ 并且 parentname 为temp 的父亲 int cmp;cmp=CompareDate(temp-in fo.birthday,pare ntT-in fo.birthday);if(cmpchild,Visit); PreOrderTraverse(fp,T-sibli ng,Visit);void SaveNode(FILE *fp, Person &pNode)/本函数向文件fp中存取一结点pNodechar

    22、 ch=n: if(pNode)fprin tf(fp,%s %d %d”,pNode-info.n ame,pNode-in fo.birthday.year,pNode-i nfo.birthday.mo nth,pNode-i nfo.birthday.day,pNode-i nfo.marry, pNode-in fo.addr,pNode-info.li ve);%dif(pNode-info.live=0)fprin tf(fp, %d %d”,pNode-in fo.deathday.year,pNode-in fo.deathday. mon th,pNode-in fo.de

    23、athday.day);if(pNode-pare nt)fprin tf(fp, %s ,pNode-pare nt-info.n ame);elsefprin tf(fp, %s,-1);fprintf(fp, %c,ch);227查看某代信息查看某代信息函数的相关代码如下:int COperati onF amilytree:l nGen erati on Pos(Pers on pNode) /本函数返回pNode结点在第几代int pos=1;Pers on p;p=pNode-pare nt;for(;p!=0;p=p-pare nt)pos+;return pos;2.2.8按姓

    24、名查找按姓名查找函数的相关代码如下:void COperatio nF amilytree:F in d(Pers on& T,Pers on& Tn ame,char* n ame)/本函数以T为根结点开始,搜索结点信息中名字等于 name的结点if(T) /如果T存在/T结点姓名和name相同,把T结/对T的兄弟递归搜索/对T的孩子递归搜索if(strcmp(T-i nfo. name, name)=0) 点指针传给TnameTn ame=T;elseFi nd(T-sibli ng,T name, name); Fin d(T-child,T name ,n ame);2.2.9按生日查

    25、找按生日查找函数的相关代码如下:void COperati onF amilytree:F in d(Pers on &T, Person*& Tn ame,i nt mon th, int day)/本函数以T为根结点开始,搜索结点信息中生日等于 month,day的结点,/并把所有符合条件的结点指针值存入以 Tname为起始地址的地址数组中if(T) /如果T存在if(T-in fo.birthday. mon th=month&T-in fo.birthday.day=day)/T结点生日与所给相同,把T结点指针传给Tname,同时Tname指针前进 Pers on temp;temp=

    26、new Pers onN ode;temp=T;if(temp-in fo.birthday. mon th=month&temp-in fo.birthday.day=day)*Tn ame=temp;Tn ame+;temp=NULL;Find(T-child,Tname,month,day); / 对 T 的孩子递归搜索Find(T-sibling,Tname,month,day); / 对 T 的兄弟递归搜索2.2.10查看成员关系查看成员关系函数的相关代码如下:void CFamilytreeDlg:O nF amilytreeRelatio ns()/ TODO: Add your

    27、 comma nd han dler code hereCRelatio nsDIg dlg;if(dlg.DoModal()=IDCANCEL)return;UpdateData(FALSE);int pos1,pos2;Pers on on eself=0;char name1MAX_CHARNUM, name2MAX_CHARNUM;strcpy (n ame1,dlg.m_first name);operFamilytree.Fi nd(operFamilytree.GetRoot(),o neself, name1); if(on eself)pos1=operFamilytree .InGen erati on Pos( on eself);elseAfxMessageBox(本家谱中找不到+CString(name1)+!); return;Pers on p,q;CString generation;gen erati on+=on eself- info.n ame;gen eratio


    注意事项

    本文(家谱管理系统设计实现分析.docx)为本站会员主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

    copyright@ 2008-2023 冰点文库 网站版权所有

    经营许可证编号:鄂ICP备19020893号-2


    收起
    展开