家谱管理系统设计与实现

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

课程设计报告

课程名称《数据结构》

课题名称排序综合

专业

班级

学号

姓名

联系方式

指导教师

20 11 年12 月21 日

目录

1. 问题陈述 (3)

2.设计方法阐述 (3)

2.1总体规划 (3)

2.2功能构想 (4)

2.2.1增加成员 (4)

2.2.2修改成员资料 (5)

2.2.3删除成员 (6)

2.2.4打开家谱 (7)

2.2.5新建家谱 (8)

2.2.6保存家谱 (10)

2.2.7查看某代信息 (11)

2.2.8按姓名查找 (12)

2.2.9按生日查找 (12)

2.2.10查看成员关系 (13)

2.2.11按出生日期排序 (14)

2.3板块整合 (15)

2.4调试分析 (19)

3.总结 (19)

4. 测试结果 (20)

1.问题陈述

家谱用于记录某家族历代家族成员的情况与关系。现编制一个家谱资料管理软件,实现对一个家族所有的资料进行收集整理。支持对家谱的存储、更新、查询、统计等操作。并用计算机永久储存家族数据,方便随时调用。

2.设计方法阐述

2.1总体规划

在动手编制程序之前,先要做好程序的规划,包括程序储存数据所用的结构,数据类型等等,只有确定了数据类型和数据结构,才能在此基础上进行各种算法的设计和程序的编写。

首先是考虑数据类型。在家谱中,家族成员是最基本的组成部分,对于家族管理中,已经不能再进行细分了,所以选定家族成员作为数据的基本类型,并在程序中定义COperationFamilytree 类。其中COperationFamilytree 类的各种属性可以根据需要进行添加或删除,从日常生活应用的角度出发,制定了COperationFamilytree 类中包含了一下属性:

char name[MAX_CHARNUM]; //姓名

Date birthday; //出生日期

In tsex; //性别

char addr[MAX_CHARNUM]; //基本资料

int live; //健在否

Date deathday; //死亡日期

int ChildNums(Person pNode) ; //返回pNode孩子数

intInSiblingPos(Person pNode); //返回pNode在其兄弟中的排行

为方便计算机进行比较,在familytree类的某些属性中用数字代替了某些不会改变的字符串,譬如性别(1代表男,0代表女)、判断是否健在(1为是,0为否)。在设置日期上,为方便以后的计算与比较,也将日期用整型数字表示19990505表示1999年5月5日,这种表示方法只需在输入和输出上作少许的运算便可方便地与日期进行转换。在家族关系的表示

上,并没有用相关家属的姓名作为储存数据,而仅仅是存储了各关系亲属的ID,方便日后作为指针指示调用相对应的家族成员。其中在属性pNode上,其表示的是下一个同父母的弟或妹ID,也就是说,当某家族成员有若干个子女,其pNode仅指向第一个孩子,其余的孩子如何表示呢?可以通过第一个孩子的pNode指示,如此类推,直到孩子的pNode =0为止。这样就可以避免需在程序设计时预定父母可以拥有的孩子数,有多少孩子就表示多少,实现了动态的储存数据。

在选择数据结构方面,从直观来说,选择树型结构通过链表来连接数据无疑是最直观易懂的,我在一开始构思的时候也是从树型结构去想的,但当构思到如何存储和提取数据是,便发现了问题。毫无疑问,用指针来处理数据的确是方便直观,但当我要储存数据是,便发现把指针储存进去是没有作用的,因为当我们下一次读取数据的时候,数据内存地址已经不同了,不在是我们上次存储数据时的地址,也就是说指针这时已经是没有作用了。要解决这样的问题,我们必须要在存储数据之前,先家族树序列化,用数组(或者其他可以用数字表示关系的方法)来存储,并且,再下一次读取数据时,再把数据按照序列号重新组成一个家族树,过程比较繁复,而且实现起来也不容易。所以我便考虑直接用数组来存储数据,即使是在内存中也用数组来处理数据间的联系。运用顺序表这个结构虽然不是那么直观,但在查找数据时的算法设计比较简单容易实现,效率高,而且在内存中的数据可以直接读入到文件中,文件中的数据也可以直接读入内存,不需要进行转换。所以在衡量的各个方面之后,我决定用数组来处理数据间的联系。

2.2功能构想

构想好总体规划之后,便开始设计程序中需要用到的各个功能函数,初步构想是要先实现最基本的几项功能,其中数据操作的有:增加成员,修改成员资料,删除成员;数据存取的有:打开家谱,新建家谱,保存家谱,另存家谱;数据查询的有:查看某代信息,按姓名查找,按生日查找,查看成员关系,按出生日期排序等等。

2.2.1增加成员

这项功能做得不够理想,在规划时没有把成员以配偶的形式增加,而只能以子女的形式增加。

对应的函数代码如下:

void COperationFamilytree::Add(Person parent, Person addNode)

{

//本函数把addNode结点加入到其父结点parent下

addNode->child=addNode->sibling=0; //把欲加入的结点所有指针域置空

addNode->parent=parent; //因addNode欲加为parent的孩子,故addNode结点的父指针域应指向parent

if(parent==0){ //若parent为0,则表示欲加addNode为根结点

if(T==0){ //若本为空家谱

T=addNode; //把addNode当成根结点

return;

}

addNode->child=T; //使原来的根结点成为新根结点的孩子

T->parent=addNode;

T=addNode;

return;

}

if(parent->child==0) //parent无孩子,把addNode加入其孩子parent->child=addNode;

else

InsertSibling(parent->child,addNode); //把addNode加到parent孩子的兄弟域中

}

2.2.2修改成员资料

修改成员这项功能实现起来比较简单,找到要修改成员的名字,再输入新修改的值,整个函数没有什么需要运用算法的地方,但如果想真正写好这个函数,则需要考虑相当多的细节,譬如各个输入项目的错误处理等等,要非常全面地考虑各项细节。函数代码如下:

void CFamilytreeDlg::OnModify()

{

// TODO: Add your command handler code here

if(operFamilytree.GetRoot()==0)

return;

CModifyInfoDlg dlg;

HTREEITEM hItem;

hItem=m_peTree.GetSelectedItem();

dlg.m_newname=m_peTree.GetItemText(hItem);

Person oneself=0;

char oldname[MAX_CHARNUM];

strcpy(oldname,dlg.m_newname);

operFamilytree.Find(operFamilytree.GetRoot(),oneself,oldname);

if(dlg.DoModal()==IDCANCEL)

return;

UpdateData(FALSE);

Person newValue=new PersonNode;

相关文档
最新文档