家谱管理系统设计与实现

家谱管理系统设计与实现
家谱管理系统设计与实现

课程设计报告

课程名称《数据结构》

课题名称排序综合

专业

班级

学号

姓名

联系方式

指导教师

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;

strcpy(newValue->https://www.360docs.net/doc/f52757669.html,,dlg.m_newname); //判断家谱中是否已有用户给定的新名字

if(strcmp(newValue->https://www.360docs.net/doc/f52757669.html,,oldname)==0) ; //用户不修改姓名

else{

Person p=0;

operFamilytree.Find(operFamilytree.GetRoot(),p,newValue->https://www.360docs.net/doc/f52757669.html,); //查找家谱中有没有此人

if(p!=0){

AfxMessageBox("家谱中已有此人!");

delete newValue;

return;

}

}

strcpy(newValue->info.addr,dlg.m_newaddr);

newValue->info.marry=dlg.m_marry;

newValue->info.live=dlg.m_live;

newValue->info.birthday.day=dlg.m_birthday_day;

newValue->info.birthday.month=dlg.m_birthday_month;

newValue->info.birthday.year=dlg.m_birthday_year;

if(!newValue->info.live){ //如若过世,则应有死亡日期

newValue->info.deathday.day=dlg.m_deathday_day;

newValue->info.deathday.month=dlg.m_deathday_month;

newValue->info.deathday.year=dlg.m_deathday_year;

if(!operFamilytree.IsDateValid(newValue->info.deathday)){

AfxMessageBox("此人信息中死亡日期不合实际!");

delete newValue;

return;

}

if(https://www.360docs.net/doc/f52757669.html,pareDate(newValue->info.deathday,newValue->info.birthday)==-1){

AfxMessageBox("此人死亡日期不可能比其出生日期早!");

return;

}

}

operFamilytree.Modify(oneself,newValue);

RefreshTree();

RefreshList();

IsFamilytreeModified=true; //置家谱修改标记为真

delete newValue;

}

2.2.3删除成员

用数组来储存数据,,最麻烦的就是删除数组元素了,在这个程序中,删除数组不但意味着要重新排列各成员,还要重新更新各成员的关系,所以我个人认为在这个程序中,删除成员函数可以说是一个难点。通过分析,发现删除成员的情况就只有两种,只要针对这两种情况处理好删除,就可以完成成员删除这个功能。

1,删除的成员是出于家族中最底层的,也就是删除该成员不会牵连其他成员,但这也需要处理好其父母的孩子数。

2,删除的成员还有子孙,则需要连带所有子孙都要删除出家谱。遇到这种情况,不但要像上一种情况那样处理父母和兄弟姐妹的关系,还要记录牵连删除的总人数,因为删除不再是简单删除了一个人,而是若干个,通过递归调用,可以统计出需要删除的数目删除函数的相关代码如下:

void COperationFamilytree::Delete(Person &rootNode)

{

//本函数删除以rootNode为根结点的所有结点

if(rootNode->parent) //如果rootNode有父结点

if(rootNode->parent->child==rootNode) //如果rootNode为其父结点的第一个孩子

rootNode->parent->child=rootNode->sibling; //因要删掉rootNode,故把其父结点的孩子指针指向rootNode的第一个兄弟

else{ //如果rootNode不是父结点的第一个孩子

Person p=rootNode->parent->child; //找到rootNode应在兄弟中的位置

for(;p->sibling!=rootNode;p=p->sibling)

;

p->sibling=rootNode->sibling; //插入到兄弟中

}

PostOrderTraverse(rootNode->child,DestroyNode);//删除以rootNode->child为根结点的所有结点

if(rootNode==T) //删除rootNode结点。如果rootNode为根结点,则删除根结点T

DestroyNode(T);

else

DestroyNode(rootNode);

}

2.2.4打开家谱

打开家谱函数的相关代码如下:

int COperationFamilytree::ReadNode(FILE *fp, Person &T,char* parentname)

{

//本函数从文件fp中读取信息到结点T中,并读取结点的父亲名字到字符数组parentname中//分别读取结点值,为:姓名,出生日期(年,月,日),婚否,地址,健在否,(如过世,还有死亡日期) fscanf(fp,"%s%d%d%d%d%s%d",T->https://www.360docs.net/doc/f52757669.html,,&T->info.birthday.year,&T->info.birth day.month,

&T->info.birthday.day,&T->info.marry,T->info.addr,&T->info.live);

if(T->info.live==0)

fscanf(fp,"%d%d%d",&T->info.deathday.year,&T->info.deathday.month,

&T->info.deathday.day);

fscanf(fp,"%s",parentname);

if(!IsDateValid(T->info.birthday)) //出生日期合法性检查

return FILE_DATA_NOT_PRACTICAL;

if(T->info.live==0) //若过世,死亡日期合法性检查

{ if (CompareDate(T->info.birthday,T->info.deathday)!=-1)

return FILE_DATA_NOT_PRACTICAL;

if(!IsDateValid(T->info.deathday))

return FILE_DATA_NOT_PRACTICAL;}

return OK;

}

2.2.5新建家谱

新建家谱函数的相关代码如下:

void COperationFamilytree::NewFamilytree()

{

//本函数新建一空家谱

DestroyFamilytree(); //删除原有家谱

T=0;

}

int COperationFamilytree::CreateFamilytree(CString filename)

{

//本函数建立一新家谱

DestroyFamilytree(); //建立一新家谱之前,清空原有家谱

FILE* fp;

if((fp=fopen(filename,"r"))==0) //打开文件filename

return READ_FILE_ERROR;

T=new PersonNode; //定义根结点

if(!T)

return NOT_ENOUGH_MEMORY;

T->child=0;

T->sibling=0;

T->parent=0;

Person parentT, temp; //定义两个临时结点

char parentname[MAX_CHARNUM]; //定义一个临时字符串数组

//读取根结点值,(姓名,出生日期(年,月,日),婚否,地址,健在否,(如过世,还有死亡日期))

int result;

result=ReadNode(fp,T,parentname);

if(result==FILE_DATA_NOT_PRACTICAL){

delete T; //若不合法,删除申请的堆空间

T=0;

return result;

}

if(strcmp(T->https://www.360docs.net/doc/f52757669.html,,parentname)==0){ //根结点名字与其父亲名字相同,说明为空树

delete T;

T=0;

return PEDIGREE_EMPTY;

}

temp=new PersonNode; //申请一结点

if(!temp){ //申请失败

DestroyFamilytree(); //释放申请空间

return NOT_ENOUGH_MEMORY;

}

result=ReadNode(fp,temp,parentname);

while(strcmp(temp->https://www.360docs.net/doc/f52757669.html,,parentname)&&strcmp(temp->https://www.360docs.net/doc/f52757669.html,,"end")){ //读取信息结束的条件是两个人的名字同为end

if(result==FILE_DATA_NOT_PRACTICAL){ //若数据不合法,释放已申请空间,然后返回

delete temp;

DestroyFamilytree();

return result;

}

parentT=0;

Find(T,parentT,parentname); //找到parentname所在结点parentT

if(parentT){ //如果parentT存在,说明parentname在家谱中

//并且parentname为temp的父亲int cmp;

cmp=CompareDate(temp->info.birthday,parentT->info.birthday);

if(cmp<0){ //若孩子出生日期比父亲大,则不对delete temp;

DestroyFamilytree();

return FILE_DATA_NOT_PRACTICAL;

}

temp->child=temp->sibling=0;

temp->parent=parentT; //temp的父指针指向parentT;

if(parentT->child){ //parentname已经有孩子

InsertSibling(parentT->child,temp);

}//if

else //parentname无孩子,则temp应为parentT->child=temp; //parentname的第一个孩子}//if

else{ //parentT不存在,说明家谱中不存在parentname此人DestroyFamilytree(); //返回出错信息

return FILE_DATA_ERROR;

}

temp=new PersonNode; //申请一结点

if(!temp){ //申请失败

DestroyFamilytree(); //释放申请空间

return NOT_ENOUGH_MEMORY;

}

result=ReadNode(fp,temp,parentname); //继续读取数据}//while

if(temp)

delete temp;

fclose(fp);

return OK;

}

2.2.6保存家谱

保存家谱函数的相关代码如下:

int COperationFamilytree::SaveFamilytree(CString filename)

{

//本函数保存家谱到文件filename中

FILE* fp;

if((fp=fopen(filename,"w"))==0) //打开文件filename

return WRITE_FILE_ERROR;

PreOrderTraverse(fp,T,SaveNode); //从根结点开始存储家谱数据

//置家谱数据结束标记(一结点的名字与其父结点的名字同为end)

fprintf(fp,"%s %d %d %d %d %s %d %s","end",1999,12,

2,1,"end",1,"end");

fclose(fp);

return OK;

}

void COperationFamilytree::PreOrderTraverse(FILE* fp,Person &T, void (__cdecl *Visit)(FILE* fp,Person &))

{

//本函数把所有以T结点为根结点的结点值存到文件fp中

if(T){

(*Visit)(fp,T);

PreOrderTraverse(fp,T->child,Visit);

PreOrderTraverse(fp,T->sibling,Visit);

}

}

void SaveNode(FILE *fp, Person &pNode)

{

//本函数向文件fp中存取一结点pNode

char ch='\n';

if(pNode){

fprintf(fp,"%s %d %d %d %d %s %d ",pNode->https://www.360docs.net/doc/f52757669.html,,pNode->info.birthday.year,

pNode->info.birthday.month,pNode->info.birthday.day,pNode->info.marry,

pNode->info.addr,pNode->info.live);

if(pNode->info.live==0)

fprintf(fp," %d %d %d ",pNode->info.deathday.year,pNode->info.deathday.month,

pNode->info.deathday.day);

if(pNode->parent)

fprintf(fp," %s ",pNode->parent->https://www.360docs.net/doc/f52757669.html,);

else

fprintf(fp," %s","-1");

fprintf(fp," %c",ch);

}

}

2.2.7查看某代信息

查看某代信息函数的相关代码如下:

int COperationFamilytree::InGenerationPos(Person pNode)

{

//本函数返回pNode结点在第几代

int pos=1;

Person p;

p=pNode->parent;

for(;p!=0;p=p->parent)

pos++;

return pos;

}

2.2.8按姓名查找

按姓名查找函数的相关代码如下:

void COperationFamilytree::Find(Person& T,Person& Tname,char* name)

{

//本函数以T为根结点开始,搜索结点信息中名字等于name的结点

if(T){ //如果T存在

if(strcmp(T->https://www.360docs.net/doc/f52757669.html,,name)==0) //T结点姓名和name相同,把T结点指针传给Tname

Tname=T;

else{

Find(T->sibling,Tname,name); //对T的兄弟递归搜索

Find(T->child,Tname,name); //对T的孩子递归搜索

}

}

}

2.2.9按生日查找

按生日查找函数的相关代码如下:

void COperationFamilytree::Find(Person &T, Person*& Tname,int month, int day)

{

//本函数以T为根结点开始,搜索结点信息中生日等于month,day的结点,

//并把所有符合条件的结点指针值存入以Tname为起始地址的地址数组中if(T){ //如果T存在

if(T->info.birthday.month==month&&T->info.birthday.day==day){

//T结点生日与所给相同,把T结点指针传给Tname,同时Tname指针前进

Person temp;

temp=new PersonNode;

temp=T;

if(temp->info.birthday.month==month&&temp->info.birthday.day==day)

{

*Tname=temp;

Tname++;

}

temp=NULL;

}

Find(T->child,Tname,month,day); //对T的孩子递归搜索

Find(T->sibling,Tname,month,day); //对T的兄弟递归搜索}

}

2.2.10查看成员关系

查看成员关系函数的相关代码如下:

void CFamilytreeDlg::OnFamilytreeRelations()

{

// TODO: Add your command handler code here

CRelationsDlg dlg;

if(dlg.DoModal()==IDCANCEL)

return;

UpdateData(FALSE);

int pos1,pos2;

Person oneself=0;

char name1[MAX_CHARNUM],name2[MAX_CHARNUM];

strcpy(name1,dlg.m_firstname);

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

if(oneself)

pos1=operFamilytree.InGenerationPos(oneself);

else{

AfxMessageBox("本家谱中找不到"+CString(name1)+"!");

return;

}

Person p,q;

CString generation;

generation+=oneself->https://www.360docs.net/doc/f52757669.html,;

generation+="在家谱中的位置: ";

for(q=oneself,p=q->parent;p!=0;p=p->parent){

generation+=q->https://www.360docs.net/doc/f52757669.html,;

generation+= "->";

q=p;

}

generation+=q->https://www.360docs.net/doc/f52757669.html,;

generation+="\n";

oneself=0;

strcpy(name2,dlg.m_secondname);

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

if(oneself)

pos2=operFamilytree.InGenerationPos(oneself);

else{

AfxMessageBox("本家谱中找不到"+CString(name2)+"!");

return;

}

generation+=oneself->https://www.360docs.net/doc/f52757669.html,;

generation+="在家谱中的位置: ";

for(q=oneself,p=q->parent;p!=0;p=p->parent){

generation+=q->https://www.360docs.net/doc/f52757669.html,;

generation+= " -> ";

q=p;

}

generation+=q->https://www.360docs.net/doc/f52757669.html,;

generation+="\n\n";

CString cmpResult;

if(pos1>pos2)

cmpResult.Format("%s在第%d代,%s在第%d代,%s是%s的晚辈.",name1,pos1,name2

,pos2,name1,name2);

else if(pos1

cmpResult.Format("%s在第%d代,%s在第%d代,%s是%s的长辈.",name1,pos1,name2

,pos2,name1,name2);

else

cmpResult.Format("%s与%s同在第%d代.",name1,name2,pos2);

generation+=cmpResult;

AfxMessageBox(generation);

}

2.2.11按出生日期排序

按出生日期排序函数的相关代码如下:

void COperationFamilytree::SortByBirthday(QuickSortNode *order)

{

//本函数对顺序表order以出生日期的大小排序

int totalNums=0;

QuickSortNode* startaddr=order;

startaddr++;

GetPersonNums(T,totalNums);

CopyInfoFromBiTreeToArray(T,startaddr);

QuickSort(order,1,totalNums);

}

2.3板块整合

以上的功能设计生成的各种函数文件仅是独立的各个板块,要将这些函数有机地联系起来,才能形成可以应用的程序,首先我用了一个DefineStruct.h声明数据类型与各个应用函数,其代码如下:

根据家谱的特点,采用孩子-兄弟的二叉树链表表示法(链表的基本单位为以结构PersomNode表示的结点),各种操作以COperationFamilytree 类来实现。

以下是CoperationFamilytree类包含的数据成员及基本操作

class COperationFamilytree//定义家族成员结构

{

public:

COperationFamilytree();

//构造函数

virtual ~COperationFamilytree();

//析构函数

void NewFamilytree();

//新建一空家谱

int CreateFamilytree(CString filename);

//从输入文件filename 中读取数据建立家谱

void DestroyFamilytree();

//删除家谱

int SaveFamilytree(CString filename);

//保存家谱

void PreOrderTraverse(FILE* fp,Person& T ,void (*Visit)(FILE* fp,Person& T));

//先序遍历(为保存家谱而做)

void PostOrderTraverse(Person& T,void (*Visit)(Person& T));

//后序遍历(为删除家谱而做)

void Find(Person& T,Person& Tname,char* name);

//从根结点出发,搜索name 所在结点,如找到,存于Tname 中,找不到,Tname 为0

//使用前确保Tname 指针为0

void Find(Person&T,Person*& Tname,int month,int day);

//从根结点出发,搜索家谱中birthday.month 等于month,birthday.day 等于day 的所有结//点,如找到,存于以Tname 为首地址的指针数组中,找不到,Tname 为0 使用前确保Tname //指针为0

void Add(Person parent,Person addNode);

//把addnode 加为结点parent 的孩子

void Delete(Person& rootNode);

//删除以rootNode 为根结点的所有结点

void Modify(Person& pNode,Person newValue);

//修改pNode 结点为新值newValue

void SortByBirthday(QuickSortNode* order);

//对家谱以出生日期排序,并把排序结果放在数组order 中

void GetPersonNums(Person&T,int& personNums);

//得到家谱中总人数

int InGenerationPos(Person pNode);

//返回pNode 在家谱中是第几代

int InSiblingPos(Person pNode);

//返回pNode 在其兄弟中的排行

int ChildNums(Person pNode);

//返回pNode 孩子数

int CompareDate(Date date1,Date date2);

//比较两日期的大小

bool IsDateValid(Date date);

//检验日期是否合法

Person& GetRoot();

//得到根结点

friend void SaveNode(FILE* fp,Person& pNode);

//保存结点pNode 到文件fp 中

friend void DestroyNode(Person& pNode);

//删除结点

private:

Person T;

//二叉树的根结点

int ReadNode(FILE* fp,Person&T,char* parentname);

//从文件fp 中读取信息到结点T 中,读取此结点的父亲姓名到parentnaem 中(供CreateFamilytree 函数调用)

void InsertSibling(Person& firstSibling,Person insertSibling);

//把insertSibling 插入到以firstSibling 为首的兄弟中(供CreateFamilytree 函数调用)

void CopyInfoFromBiTreeToArray(Person&T,QuickSortNode*&order);

//把家谱中以pNode 结点为根结点的出生日期拷贝到快速排序结构数组order 中(供SortByBirthday 函数调用)

void QuickSort(QuickSortNode* order,int low,int high);

//对order[low...high]中的记录进行快速排序(供SortByBirthday 函数调用)

int Partition(QuickSortNode* order,int low,int high);

//对order[low..high]中的记录进行一次排序(供QuickSort 函数调用)

bool IsLeapYear(int year);

//判断是否闰年(供IsDateValid 调用,以检查日期是否合法)

}

根据MFC 的特点,采用CfamilytreeDlg 类实现用户窗口界面指令对于家谱的各种操作。class CFamilytreeDlg : public CDialog

{

public:

void SaveTip();

//保存提示

void InitListCtrl();

//初始化列表控件

void RefreshTree();

//刷新树,(即刷新显示)

void RefreshList();

//刷新列表

void DisplayFamilytree(Person& pNode);

//显示树

void DisplayInListCtrl(Person pNode);

//把pNode 结点的信息在列表控件中显示出来

void Display(CString temp);

//在列表控件中显示其他信息

void FindInTree(HTREEITEM& hRootItem,HTREEITEM& hItem,char* name);

//在树hRootItem 中查找name 所在结点,如找到,把其结点句柄存入hItem 中,找不到,//hItem 为0.注意,使用该函数时,确保hItem 初值为0

void BirthdayTip();

//每次打开一新家谱文件时的生日提示

void DisplayGenerationInfo(Person& pNode,bool& flag,int count,int generation);

//显示所有第generation 代人的信息

void AddToTree(HTREEITEM hParentItem,Person addnode );

//把addnode 加入到树的hParentItem 结点中去

private:

char savepath[MAX_CHARNUM];

//家谱第一次被保存时的路径

bool IsFamilytreeModified;

//家谱是否被修改标记

COperationFamilytree operFamilytree;

//对家谱操作的一个类实例,所有的家谱操作均由它调用成员函数来完成

};

为使程序结构趋于清晰,分别使用CAddInfoDlg、CBirthdayDlg、CDelInfoDlg、CFileOpenAndSaveDlg、CModifyInfoDlg、CPersonalInfoDlg、CRelationsDlg、CSearchGenerationDlg 类实现用户窗口对于家谱的增加成员、按生日查找、删除成员、文件输入输出、修改成员信息、按名字查找、成员关系显示、按代数显示等各种操作。

纵上所示,本程序的两主要类为

CoperationFamilytree 类:所有对家谱的操作均由此类完成。

CFamilytreeDlg 类:所有对用户菜单命令的解释均由此类完成,然后调用CoperationFamilytree 类的成员函数执行命令并显示结果。

2.4调试分析

1.该课程设计只有一个主要类,即对孩子——兄弟二叉树的操作类。该类主要包括文件读取函数、创建孩子——兄弟二叉树函数、在树中查找函数、遍历函数以及对树中结点进行加入、删除、修改的函数。由于树存储结构的特殊性,故编制这些算法时大量使用了递归,虽然这样做可能会降低程序的执行效率,但程序的易读性较强。

2.在调试时,遇到的几个问题如下:

(1)建立树时,由于新申请结点的孩子指针、兄弟指针、及双亲指针均未赋空值。而在以后的函数中对树进行递归操作时均以这些指针值中的一个或几个是否为空作为递归结束条件。从而导致调用这些函数时出现系统保护异常(使用了不安全的指针)。

(2)刚开始删除结点时,只考虑到删除其本身结点的情况,而删除其孩子结点的情况未考虑到,故在删除某些结点时使树出现了“断链”现象。故在程序代码中对删除某一结点进行操作时,首先要判断此结点是否有孩子及兄弟,然后进行相应操作。

(3)刚开始进行程序概要设计时,曾考虑到用控制台下的文本方式作为程序界面,实际操作后发现并不理想。一方面字符形式的界面友好性较差,另一方面显示整个家谱树的信息时不方便。故考虑用VC++中MFC 类自带的树型控件显示家谱层次,而用列表控件显示家谱中的信息。用后效果不错。

3总结

通过这次大作业,体会很深刻,将一直以来学到的东西都运用到实际上来,学以致用,对所学知识有了更深刻的理解,同时还发现了许多平时在书本上没有遇见过的问题,促进了自己对知识的渴望,遇见了问题,就希望能够通过查找课外书来解决它们。刚接触题目的时候,自己就有了一定的想法,觉得这个程序做起来是问题不大的,但到了自己真正开始编程的时候却发现远远没有想象中那么简单,很多细节的问题没有预想到,很多关系的处理想得过于简单,以至于实施起来遇到了很大的困难,花了大量的时间。同时还有一个比较深刻的体会就是要尽量多在源码上作注释,以前编一些功能简单的程序,总能很清楚每个函数和每

个变量的作用,但到了做这个大作业,由于分开了各个功能板块去实现,很多时候是做了后面就忘了前面,后来意识到这个问题,便开始在编程时加入注释,而且是越详细越好,这样做了以后,很多时候需要查看自己原来写的源代码,也能够很方便地了解了,跟上了思路,也方便以后的维护。

关于这个程序的缺点方面,由于自己花的时间不是很多,再加上知识有限,编写出来的界面不够友好,在功能上还是有不完善的地方,譬如说各项数据的统计还没有弄,数据的存储还不够理想等等。

对于这个程序的改进,我自己还是有不少想法的,因为怎么说都是自己亲手编制出来的程序,当然是希望尽善尽美。首先是需要加强数据的存储这方面的知识,使自己编写出来的程序能以一种标准的格式存储下来,方便以后其它程序的读取。

总的来说,通过这次作业,收获还是挺多的,也发现了不少的问题,并给自己以后的学习指引了方向,知道自己缺少哪方面的知识,需要补充哪些知识等等。自己将会以这次作业为契机,看更多编程方面的书籍,不断充实自己的知识库。

4.测试结果

家谱管理实验报告

Project 3 家谱管理

一、题目 用树型结构实现家族成员信息管理,(如建立、删除、查询、统计、打印等) 二、数据结构与算法 1.定义树结点node { string name; node *left; node *right; string sex;//male or female int num;//结点编号 node() { name = ""; left = right = NULL; num = 0; sex = "male"; } }; 2.定义class tree{};实现不同对树的操作 其中,以static int count记录节点总数; 以static int height记录树高度; 以node* root作为头指针; 以node* arr[maxnode]将每个节点的指针记录在数组里。 3.对于该树的操作: a. 创建树: 首先此project中树由男性为根结点。男性的左孩子是其兄弟,右孩子是其第一任妻子,第一任妻子的右孩子是其第二任妻子,每个妻子的左孩子是其与这位妻子的孩子。如此递归生成家谱。 输入时,用0表示左孩子,1表示右孩子,以1010等的字符串输入结点位置来创造结点。创建后用函数cheak来检验创造的树是否正确,具体来说就是避免创建树时出现有结点没有父结点的情况。 b.删除结点:以结点的name成员搜索结点,删除结点及其子树。 c.查询结点:以结点的name成员搜索结点,打印该结点的父母兄弟、妻 子、男孩。 d.统计函数:统计家谱总数。本project中通过#define定义打印屏幕宽 度screen_width为96,最多结点maxnode为32,因此树高度不超过5层,总数count不超过32. (linux下测试,终端宽度可以任意,windows下的话只能是80) e.打印:采用广度优先搜索遍历来打印树。

数据结构家谱管理系统范本

数据结构家谱管理 系统

宁波大红鹰学院 信息工程学院 课 程 设 计 报 告 项目名 家谱查询系统 称: 白钰琦 项目组 长: 徐程凯、徐海域、项鸿伟 项目成 员: 10计科1班 班级名 称: 计算机科学与技术 专业名 称: 完成时间: 12月1日 信息工程学院制 目录 一、案例描述 ............................................................ 错误!未定义书签。 1、总体描述 ....................................................... 错误!未定义书签。 2、模块描述 ....................................................... 错误!未定义书签。

二、设计思路 ............................................................ 错误!未定义书签。 三、程序设计 ............................................................ 错误!未定义书签。 1、数据结构描述................................................ 错误!未定义书签。 2、主函数及其流程图........................................ 错误!未定义书签。 3、源程序 ........................................................... 错误!未定义书签。 四、调试与分析 ........................................................ 错误!未定义书签。 1、主菜单 ........................................................... 错误!未定义书签。 2、显示家谱信息................................................ 错误!未定义书签。 3、显示家谱中第n代人所有信息 .................... 错误!未定义书签。 4、按姓名查找某人并相应输出 ........................ 错误!未定义书签。 5、按出生日期查找家谱成员信息 .................... 错误!未定义书签。 6、为家谱中成员添加孩子信息 ........................ 错误!未定义书签。 7、为家谱中成员添加妻子信息 ........................ 错误!未定义书签。 8、删除家谱中成员及其后代信息 .................... 错误!未定义书签。 9、修改家谱中成员信息.................................... 错误!未定义书签。 10、确定家谱中两个成员关系 .......................... 错误!未定义书签。 11、按出生年月排序家谱 .................................. 错误!未定义书签。 五、设计总结 ............................................................ 错误!未定义书签。 1、完成情况 ....................................................... 错误!未定义书签。 2、心得体会 ....................................................... 错误!未定义书签。

家谱管理系统的源代码

#include #include #include #include struct per{ int data; char name[20]; char brith[20]; char marry; char address[20]; char live; char dietime[20]; char parent[20]; int generation; int child[10]; int numberchild; per(){ for(int i=0;i<20;i++) name[i]='\0'; for(i=0;i<20;i++)

brith[i]='\0'; for(i=0;i<20;i++) address[i]='\0'; for(i=0;i<20;i++) dietime[i]='\0'; for(i=0;i<10;i++) child[i]=0; for(i=0;i<20;i++) parent[i]='\0'; live='\0'; marry='\0'; data=-10; generation=0; numberchild=0; } }; void setupinfo(per person[]); void display(per person[],int&); void displayhome(per person[],int&); void displayinfo(per person[],int&); void namesearch(per person[],int&);

数据结构树的实现实验报告

数据结构设计性实验报告 课程名称_____ ____ 题目名称 学生学院 专业班级 学号 学生姓名 指导教师 2010 年 7 月 6 日

抽象数据类型:树的实现 一.需求分析 树形结构是一类重要的非线性数据结构,其中以树和二叉树最为常用,直观来看,树是以分支关系定义的内部结构。树的结构在客观世界广泛存在,如人类社会的族谱和各种社会组织机构都可以用树来形象表示。树在计算机领域中也得广泛应用,如在编译程序中,可用树来表示源程序的语法结构,又如在数据库系统中,树形结构也是信息的重要组织形式之一。 二.实验目的 对某个具体的抽象数据类型,运用课程所学的知识和方法,设计合理的数据结构,并在此基础上实现该抽象数据类型的全部基本操作。通过本设计性实验,检验所学知识和能力,发现学习中存在的问题。进而达到熟练地运用本课程中的基础知识及技术的目的。 三.实验环境 1、硬件:PC机 2、软件:Microsoft Visual C++ 6.0 四.设计说明 本程序采用树的二叉链表(孩子指针-兄弟指针-双亲指针)存储表示,以下是树的结构定义和基本操作: ADT Tree{ 数据对象D:D是具有相同特性的数据元素的集合。 数据关系R: 若D为空集,则称为空树; 若D仅含有一个数据元素,则R为空集,否则R={H},H是如下二元关系: (1) 在D中存在唯一的称为根的数据元素root,它在关系H下无前驱; (2) 若D-{root}≠NULL,则存在D-{root}的一个划分D1,D2,D3, …,Dm(m>0),对于任意j ≠k(1≤j,k≤m)有Dj∩Dk=NULL,且对任意的i(1≤i≤m),唯一存在数据元素xi∈Di有∈H; (3) 对应于D-{root}的划分,H-{,…,}有唯一的一个划分H1,H2,…,Hm(m>0),对任意j≠k(1≤j,k≤m)有Hj∩Hk=NULL,且对任意i(1≤i≤m),Hi是Di 上的二元关系,(Di,{Hi})是一棵符合本定义的树,称为根root的子树。 基本操作P: InitTree(&T); 操作结果:构造空树T。 DestroyTree(&T); 初始条件:树T存在。 操作结果:销毁树T。 CreateTree(&T,definition); 初始条件:definition给出树T的定义。 操作结果:按definition构造树T。 ClearTree(&T);

家谱管理系统1

《软件综合设计》 家谱管理系统 院系:计算机科学技术学院二系 班级:计11 – 2班 姓名:刘文秀(15) 合作者:姜雪(05) 、岳奉宜(33) 指导教师:薛曼玲 2013 年 12 月 01 日

《软件综合设计》任务书 一、题目:家谱管理系统 二、设计要求 (1)刘文秀(组长)、姜雪和岳奉宜组成课程设计小组。 (2)小组成员分工协作完成。要求每个成员有自己相对独立的模块,,同时要了解其他组员完成的内容。 (3)查阅相关资料,自学具体课题中涉及到的新知识。 (4)采用结构化、模块化程序设计方法设计,功能要完善,界面美观。 (5)所设计的系统应有菜单、动画和音乐。 (6)按要求写出课程设计报告,并于设计结束后1周内提交。其主要内容包括:封皮、课程设计任务书,指导教师评语与成绩、目录、概述、软件需求分析、总体设计、详细设计、程序的调试与测试、总结与体会、结束语、程序清单(带中文注释)、参考文献等。报告一律用A4纸打印,正文的中文字体为宋体,西文字体用Time New Roma,一律用小四号字,行距采用“固定值”18磅,首行缩进2字符。1级标题中文字体为黑体,西文字体为Time New Roma,采用三号字;段落为居中、段前18磅、段后12磅、行距采用“固定值”18磅,首行缩进:无,段中不分页,与下段同页。仅一级标题上目录。 三、课程设计工作量 由于是设计小组团结协作完成设计任务,一般每人的程序量在400行有效程序行以上,不得抄袭。 四、课程设计工作计划 2013年12月2日,指导教师讲课,学生根据题目准备资料,需求分析; 2013年12月3日,设计小组进行总体方案设计和任务分工; 2013年12月4日~2013年12月10日,每人完成自己承担的程序模块并通过独立编译; 2013年12月11日~12日,将各模块集成为一个完整的系统,并录入足够的数据进行调试运行; 2013年12月13日,验收、开始撰写课程设计报告; 2013年12月18日前,提交课程设计报告和软件。 指导教师签章: 教研室主任签章

最新数据结构课程设计题目

数据结构课程设计 一、考核方法和内容 根据课程设计过程中学生的学生态度、题目完成情况、课程设计报告书的质量和回答问题的情况等按照10%、40%、30%、20%加权综合打分。成绩评定实行优秀、良好、中等、及格和不及格五个等级。评分标准: 优秀:答辩所有问题都能答出+报告良好 或报告良好+实现“提高部分”的功能; 良好:答辩所有问题都能答出+报告一般; 或报告一般+实现“提高部分”的功能; 中等:答辩大部分问题能答出+报告良好; 及格:答辩大部分问题能答出+报告一般; 以下四种,都不及格: 1)答辩几乎答不出问题; 2)报告几乎都是代码; 3)雷同部分达到60%; 4)课设报告与数据结构和c/c++关联不大。 课设报告的装订顺序如下: 任务书(签名,把题目要求贴在相应位置,注意下划线)-----目录(注意目录的格式,页码)-----1、设计任务(题目要求)-----2、需求分析(准备选用什么数据逻辑结构?数据元素包含哪些属性?需要哪些函数?为什么要这样设计?最后列出抽象数据类型定义)-----3、系统设计(设计实现抽象数据类型,包含选择什么物理存储方式?数据元素的结构体或类定义,以及各函数的设计思路,算法,程序流程图等)----4、编码实现(重要函数的实现代码)-----5、调试分析(选择多组测试数据、运行截图、结果分析)-----6、课设总结(心得体会)-----7、谢辞-----8、参考文献; 课设报告打印要求: B5纸张打印,报告总页数控制在10—15页内,报告中不能全是代码,报告中代码总量控制在3页内。版式:无页眉,有页码,页码居中 字号:小四,单倍行距 字体:宋体+Times new Romar 截图:截图要配图的编号和图的题目,如:“图1 Insert函数流程图” 二、课程设计的题目 1.长整数的加法运算 2.通讯录管理系统的设计与实现——顺序表 3.广义表的应用 4.学生成绩管理系统的设计与实现 5.家谱管理系统的设计与实现 6.集合的并、交和差运算的程序 7.运动会分数统计 8.一元多项式计算器 9.文章编辑 10.哈夫曼树及其编码 11.校园导游咨询 12.通讯录管理系统的设计与实现——单链表 13.地图着色问题 14.内部排序算法比较 15.火车售票系统 16.图书管理系统 17.客户消费积分管理系统 18.产品进销存管理系统

关于姓氏的研究报告

关于姓氏的研究报告 研究报告的计划: 一?问题的提出 我们班同姓的同学不少.他们常开玩笑说:"我们五百年前是一家!" 有一次,我翻阅《百家姓》发现许多有关姓氏的故事.于是,我们小组的成员开始了这次姓氏之旅? 二.调查方法 1.查阅《百家姓》等记载着古人姓氏的书籍,阅读有关报刊,上网查找浏览,了解本小组成员的姓氏来源和历史上的名人. 2.走访有关部门,了解本小组成员姓氏的人口和分布情况. 3.通过便捷的途径,搜集本小组成员姓氏的名人,了解名人的故事. 三.调查情况和资料整理 信息渠道 涉及的方面 具体内容 书籍报刊 黄姓的来源 公元前648年,楚成王责备黄国不向楚国进贡,黄国国君错误地分析形势,既不理会楚国的责问,又不进行任何防备,结果于当年夏天被楚国灭掉.亡国后的黄国子孙,以国名为姓氏,就是黄氏.

关于黄姓的历史和现状的研究报告 书籍报刊教科书 历史上的黄姓名人 黄歇黄霸黄盖黄巢黄庭坚黄道婆黄宗羲黄遵宪宋代状元黄定 上网 黄姓人口数量 黄姓的人口约为2876万,为全国第八大姓,大约占全国人口的2.2% 爷爷的讲述 黄姓族谱 浙江杭州?武林黄氏宗谱:清光绪间礼耕堂钞本一册藏地:美国浙江余杭?黄氏宗谱四卷:清光绪二十七年(1901)木活字本藏地:浙江余杭县文化管理委员会 关于王姓的历史和现状的研究报告 信息渠道 涉及的方面 具体内容 书籍报刊 王姓的来源

周灵王太子姬晋,因直言进谏,使王上大怒,被废为庶民,迁居到琅琊(今山东省胶南一带),世代繁衍生息.因其本为王族,世人称其"王家", 就延用成姓. 书籍报刊教科书 历史上的王姓名人 王陵王昭君王政君王凤王莽王匡王霸王朗王祥王览王导王充王献 之王羲之 上网 王姓人口数量 根据公安部治安管理局对全国户籍人口的统计分析,王姓目前仍是我国的第一姓,有9288.1万人,占全国人口总数的7.25%?也就是说每13个人中就有一个人姓王,这相当于四川省的总人口,比德国的总人口还咼1000万人. 爷爷的讲述 王姓族谱 王姓家谱文献目录:《东沙王氏支谱?家规》《三槐堂王氏族谱》 《绮山东沙王氏支谱》 关于刘姓的历史和现状的研究报告 信息渠道 涉及的方面 具体内容

数据结构家谱管理系统

//////////////////////////////////////////////////////////// /////////////////// //题目:家谱资料管理 //要求:家谱用于记录某家族历代家族成员的情况与关系。现编制一个家谱资料管理软件, //实现对一个家族所有的资料进行收集整理。支持对家谱的增加,删除,更新,统计等。 //////////////////////////////////////////////////////////// /////////////////// #include #include #include int MATEFLAG=0; typedef struct TreeNode

int Num; //记录这个人拥有几个儿女 char Name[20]; //记录这个人的姓名 char Kind; //标示节点的种类有女G男B struct TreeNode * NextNode[20]; //记录这个人的儿女struct TreeNode * Parent; //记录这个节点的父节点 }TreeNode; void CreatTree(TreeNode *Tree); void OutPutAll(TreeNode *Tree); TreeNode * SearchTree(TreeNode *Tree,char name[],int length); void MainMenue(TreeNode *Tree); void SubMenue1(TreeNode * Tree); void SubMenue2(TreeNode *Tree); void Change(TreeNode * Tree); void AddNew(TreeNode * Tree);

数据结构家谱课程设计报告

家谱管理系统 姓名:田鑫磊 学号:1514020421 (1)功能部分: 本程序共实现了6个功能分别为: 1.读出家谱并显示 2.确定指定成员在家族中的辈份 3.输出指定辈的所有成员 4.在家谱中添加新成员,并追加到文件中 5.输出指定家庭的所有成员 6. 退出本系统 (2)各功能的算法思想: 1.读出家谱并显示 存储结构用栈,按照先显示双亲,然后显示其所有孩子的顺序显示所有的家庭成员。 2.确定指定成员在家族中的辈份 用求成员所在的二叉树中的层数(按层遍历二叉树)来确定,这里采用的是递归算法3.输出指定辈的所有成员 此处定义了一个新的结构体类型(增加存储节点所在的层数),定义如下: struct { BTNode *q; int loc; //存结点所在的层数 }qu[10]; 并用一个队列来比较显示同辈分的所有成员。 4.在家谱中添加新成员,并追加到文件中 首先,输入一个新成员的名字; 然后,输入其双亲; 之后,再添加到整个存储二叉链表中。 然后,再将新的存储结构写回到文件中。 二叉链表的结点类型为:typedef struct node { ElemType data[10]; //存放成员的名字 struct node *child; //其孩子指针 struct node *brother; //其兄弟指针 }BTNode; 5.输出指定家庭的所有成员 首先,设一个栈,并设一个标记位,先置1; 然后,找到输入的要待显示的成员,将标记位置0; 再次,显示其孩子和兄弟,依次下去直到显示完其所有的亲戚。 6.退出本系统 通过一个输入字符q来控制,每完成一个功能,系统提示是否要继续操作:

(完整word版)家谱管理系统

洛 阳 理 工 学 院 课 程 设 计 报 告 课程名称 ___________________________________ 设计题目 ___________________________________ 专 业 ___________________________________ 班 级 ___________________________________ 学 号 ___________________________________ 姓 名 ___________________________________ 完成日期 ___________________________________ 数据结构课程设计 家谱管理系统 计算机科学与技术 B150405 B15080822 宋士龙 2016年12月30日

课程设计任务书 设计题目:家谱管理系统 设计内容与要求: 【问题描述】:实现具有下列功能的家谱管理系统 1). 输入文件以存放最初家谱中各成员的信息,成员的信息中均应包含以下内容:姓名、出生日期、婚否、地址、健在否、死亡日期(若其已死亡),也可附加其它信息、但不是必需的。 2). 实现数据的存盘和读盘。 3). 显示家谱。 4). 按照出生日期查询成员名单。 5). 按照姓名查询,输出成员信息(包括其本人、父亲、孩子的信息)。 6). 修改某成员信息。 【基本要求】: 界面要求:有合理的提示,每个功能可以设立菜单,根据提示,可以完成相关的功能要求。 存储结构:学生自己根据系统功能要求自己设计,但是要求相关数据要存储在数据文件中。 测试数据:要求使用1、全部合法数据;2、局部非法数据。进行程序测试,以保证程序的稳定。 测试数据及测试结果请在上交的资料中写明。 指导教师:_______________ 年月日 课程设计评语 成绩: 指导教师:_______________ 年月日

家谱管理系统(含源代码)

家谱管理系统——C语言(数据结构) 目的和要求:树形结构是一种非常重要的非线性结构,它用于描述数据元素之间的层次关系,人类家谱是树形结构的典型体现,通过此项训练让学生掌握树形结构的知识;使学生重点掌握树与二叉树的转换,二叉树的存储和遍历,和二叉树相关的一些运算;要求完成家谱信息的录入和保存,任意成员的查找及某一成员祖先、子孙、兄弟、堂兄弟的查找。 排答疑和辅导。 完整代码: #include #include #include int MATEFLAG=0; //是否入赘或嫁入这家的,1表示为是,0表示否 typedef struct TreeNode//树节点定义 { int Num; //保存此人儿女个数 char Name[20]; //保存此人姓名 char Kind; //保存此人性别,男M,女F struct TreeNode * NextNode[20]; //保存此人的儿女,NextNode[0]里存放配偶的地址struct TreeNode * Parent; //保存此节点的父节点 }TreeNode; void CreatTree(TreeNode *Tree);//创建树 void OutPutAll(TreeNode *Tree);//输出树 TreeNode * SearchTree(TreeNode *Tree,char name[],int length); void MainMenu(TreeNode *Tree); void SubMenue1(TreeNode * Tree); void SubMenue2(TreeNode *Tree); void Change(TreeNode * Tree); void AddNew(TreeNode * Tree); void OutPutMessage(TreeNode * Tree,char name[],int length); //主函数 void main() { TreeNode *Tree;//产生根节点 Tree=(TreeNode *)malloc(sizeof(TreeNode)); Tree->Parent =NULL; strcpy(Tree->Name,"0"); MainMenu(Tree);//显示主菜单 } //添加新的成员 void AddNew(TreeNode * Tree) { SubMenue2(Tree);//添加新成员界面 } //显示添加家庭信息的界面

家谱管理系统设计报告样本

目录 第一章绪论............................................................... 错误!未定义书签。第二章需求分析........................................................... 错误!未定义书签。 2.1题目...................................................................... 错误!未定义书签。 2.2设计任务.............................................................. 错误!未定义书签。 2.3数据测试.............................................................. 错误!未定义书签。第三章概要设计....................................................... 错误!未定义书签。 3.1 设计思想 ........................................................ 错误!未定义书签。 3.2 实现方法 ........................................................ 错误!未定义书签。第四章详细设计....................................................... 错误!未定义书签。 4.1功能构想.............................................................. 错误!未定义书签。 4.2界面设计.............................................................. 错误!未定义书签。 4.3增加成员.............................................................. 错误!未定义书签。 4.3.1 添加子女 .................................................... 错误!未定义书签。 4.3.2 添加配偶 .................................................... 错误!未定义书签。 4.4修改成员.............................................................. 错误!未定义书签。 4.4.1修改个人信息............................................. 错误!未定义书签。 4.4.2修改父母信息............................................. 错误!未定义书签。 4.4.3修改兄弟姐妹的信息................................. 错误!未定义书签。 4.4.4修改子女的信息......................................... 错误!未定义书签。第五章调试分析....................................................... 错误!未定义书签。

数据结构家谱管理系统报告书

数据结构大作业说明文档 一、题目的选择 这次数据结构的大作业,我的选题是家谱管理系统的设计与实现。由于平时疏于编程——针对我得个人实际——我把主要的目标定位在完成家谱管理系统得基本要求。(基本要求大纲中有,就不浪费版面了) 二、设计的思路 接到这个题目,我的总体设计思路是先为程序搭建好一个结构框架,再跟据时间的宽裕程度和其它的要求逐步增强程序的性能。 关于IO的设计: 考虑到题目要求家谱信息以树形的形式一次读入内存,而个人的各种资料现在虽然条目不多,但随着程序的升级,以后可能变得越来越大。我把树形结构和个人信息记录的文档分为两个文件保存在外存中,一个文件串行化地记录家谱树的结构信息,保存少量个人信息作为识别标志;另一个文件保存完整的个人信息,所有的个人信息以线性记录的方式记录在其中。当程序运行要读入家谱结构时,只读入保存少量记录的文件并建立起树形结构。索引时,以树形中的少量信息为依据在另一个文件中找到全部的各人信息资料。 这样的好处主要有两点: 1. 由于树形结构是串行化记录于外存,一个节点记录多次,信息大量冗余,如果树形节点中保留全部信息,必将造成大量的空间浪费;只保存作为索引的少量信息在树形结构中,节约了空间。 2. 由于结构的精简,在家谱初始化时读入内存需要的时间相应减少,节约了装载时间。 这样做存在的问题: 每次执行修改,添加,删除,查询时都要直接访问外存来取得或写入数据。内外存访问上的巨大时间差的存在,使得进行这些操作相对来说并不显得很高效。 关于树形的结构: 在树形结构的选择上,根据实际中多子女的现象选择一般树,考虑到家谱中成员可能存在的不定成员数问题,抛弃了以数组为基础的一般树方案,决定用链表来实现。 树形结构的外存保存。为了提高效率,树形结构在程序初始化时由外存文件一次读入内存,此后不管插入还是修改,删除都不再对外存的树结构保存文件进行操作,只在内存中处理,程序退出时对外存树结构文件进行一次更新。也就是说,不管在程序运行中中对家谱结构进行多少种,多少次的操作,外存的树结构文件始终只会被程序访问两次。

家谱管理系统.doc

家谱管理系统 。洛阳科技学院课程设计报告数据结构课程设计课程名称_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _家谱管理系统设计主题_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _计算机科学与技术专业_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ b 150405班级_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ b 15080822学校编号_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _宋世龙的姓氏是_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ x XXX,2006年12月30日。完成日期_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 家谱管理系统设计的内容和要求; [问题描述] 以下内容: 实现了具有以下功能的家谱树管理系统1)。输入一个文件,将每个成员的信息保存在原始家谱中,每个成员的信息应包括以下内容: 姓名、出生日期、婚姻状况、地址、生活状况和死亡日期(如果

家谱管理系统实验报告

《家谱管理系统》课程设计报告 学院:信息科学与工程学院 班级:计算机科学与技术08-4班 制作人:邢尚文 指导教师:陈黎静 山东科技大学 2011年9月1日

需求分析:本系统主要完成对家谱的相关操作和家谱人员信息的管理,包括打开家谱、新加家谱、保存家谱和家谱人员的姓名查找、某代信息查找、信息删除等。 系统的核心是利用对话框的连接和文本处理来存储和修改家谱管理系统的信息联系,其中的每一个动作都可能影响到其他的功能。 本系统实现以下功能: 1). 输入文件以存放最初家谱中各成员的信息。成员的信息中均应包含以下内容: 姓名、辈分、父辈姓名、电话。 2). 实现数据的存盘和读盘。 3). 以图形方式显示家谱。 4). 显示第n 代所有人的信息。 5). 按照姓名查询,输出成员信息 6). 删除某成员。 本系统的作用不是为了代替家谱,而是为了更好的建立家庭之间成员的联系,提供一个查询的平台,里面的族谱及文化介绍可以有效的介绍家族历史,让成员了解家族历史,向外界展示。

E-R图

程序界面与代码: using System; using System.Collections.Generic; using https://www.360docs.net/doc/f52757669.html,ponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication12 { public partial class Form1 : Form { public Form1() { InitializeComponent(); }

家谱管理系统样本

家谱管理系统 一、需求分析 本系统实现以下功能: 1). 输入文件以存放最初家谱中各成员的信息。成员的信息中均应包含以下内容: 姓名、出生日期、婚否、地址、健在否、死亡日期( 若其已死亡) 也 可附加其它信息、但不是必须的。 2). 实现数据的存盘和读盘。 3). 以图形方式显示家谱。 4). 显示第n 代所有人的信息。 5). 按照姓名查询, 输出成员信息( 包括其本人、父亲、孩子的信息) 。 6). 按照出生日期查询成员名单。 7). 输入两人姓名, 确定其关系。 8). 某成员添加孩子。 9). 删除某成员( 若其还有后代, 则一并删除) 。 10).修改某成员信息。 11).按出生日期对家谱中所有人排序。 12).打开一家谱时, 提示当天生日的健在成员。 测试要求: 1).建立至少30个成员的数据, 以较为直观的方式显示结果, 并提供文稿形式以便检查。 2).对界面的要求是: 有合理的提示, 每个功能能够设立菜单, 根据提示, 能够完成相关的功能要求。 二、设计概要 1、抽象数据类型兄弟孩子树的定义如下: ADT CSNode{

数据对象: person是兄弟孩子树中的每一个节点, T是整个树的统一体 数据关系: R1={<person i-1,person i >|<person i-1 ,person i >表示person i-1 和person i 之间有血缘关系} 基本操作: CSNode *CreatTree(fstream &outfile); 初始条件: 已经打开了文本文件PersonInfo.txt 操作结果: 创立一个兄弟孩子树T, 并把从文件中的数据送到树中, 关闭文件。 void CreatParent_step(CSNode *parent); 初始条件: 兄弟孩子树T已经存在 操作结果: 对所有的孩子节点添加指向父亲的指针 void InOrderTraverse(CSNode *T); 初始条件: 兄弟孩子树T已经存在 操作结果: 对T进行中序遍历。 bool Today_Brithday(CSNode *T); 初始条件: 兄弟孩子树T已经存在 操作结果: 根据计算机系统的时间判断几天是否有人过生日, 并显示她们的名字。 bool (int n,CSNode *T,LinkQueue &Q); 初始条件: 兄弟孩子树T已经存在, 队列Q也已经存在 操作结果: 用队列Q返回第N代人的所有信息 void Link_Info(LinkQueue Q); 初始条件: 队列Q中是第N代人的所有信息 操作结果: 显示队列中所有人的信息。 CSNode *DetectMember_Name(CSNode *T,char name[]); 初始条件: 兄弟孩子树T已经存在 操作结果: 根据输入的姓名进行查找, 如找到则返回该节点的指针。

数据结构课程设计之简易家谱 报告

编号:学号:201140410119 课程设计 教学院计算机学院 课程名称数据结构课程设计 题目简易家谱系统 专业计算机科学与技术 班级(1)班 姓名陈建辉 同组人员周海涛,石义沣,明廷柱 指导教师程细才 2013 年 1 月8 日

目录 一概述 (2) 1.课程设计的目的 (2) 2.课程设计的要求 (2) 二总体方案设计 (3) 1.简单家谱系统整体设计思路 (3) 2.简单家谱系统的主要特点及功能 (5) 三详细设计 (7) 1. 查询全部的家谱成员信息 (7) 2.确定指定成员在家族中的辈份 (7) 3.在家谱中添加新成员,并追加到文件中 (9) 四程序的调试与运行结果说明 (12) 1.实验结果截图: (12) 2.调试时遇到的问题 (12) 五课程设计总结 (13) 附录一:程序源代码 (16) 附录二:参考文献 (25)

一概述 1.课程设计的目的 1.理解和掌握该课程中的有关基本概念,程序设计思想和方法。 2.培养综合运用所学知识独立完成课题的能力。 3.培养勇于探索、严谨推理、实事求是、有错必改,用实践来检验理论,全方位考虑问题等科学技术人员应具有的素质。 4.掌握从资料文献、科学实验中获得知识的能力,提高学生从别人经验中找到解决问题的新途径的悟性,初步培养工程意识和创新能力。 2.课程设计的要求 设计要求:输入家族成员情况,建立树结构,统计家族成员人数,能查询家族成员辈份情况。 系统功能: 1. 输入、修改与删除家谱信息功能 2. 查询功能: 1)某家谱成员的所有子孙的集合 2)某家谱成员的所有祖先的集合 3)某家谱成员的所有同辈成员的集合 4)求某家谱成员的所有上一辈成员的集合 5)给出两个家谱成员,确定他们的关系

家谱管理系统 -数据结构大作业

/* 家谱管理系统 任务:实现具有下列功能的家谱管理系统 功能要求: 1). 输入文件以存放最初家谱中各成员的信息,成员的信息中均应包含以下内容: 姓名、出生日期、婚否、地址、健在否、死亡日期(若其已死亡),也可附加其它信息、但不是必需的。 2). 实现数据的存盘和读盘。 3). 以图形方式显示家谱。 4). 显示第n 代所有人的信息。 5). 按照姓名查询,输出成员信息(包括其本人、父亲、孩子的信息)。 6). 按照出生日期查询成员名单。 7). 输入两人姓名,确定其关系。 8). 某成员添加孩子。 9). 删除某成员(若其还有后代,则一并删除)。 10).修改某成员信息。 11).按出生日期对家谱中所有人排序。 12).打开一家谱时,提示当天生日的健在成员。 要求:建立至少30个成员的数据,以较为直观的方式显示结果,并提供文稿形式以便检查。界面要求:有合理的提示,每个功能可以设立菜单,根据提示,可以完成相关的功能要求。存储结构:学生自己根据系统功能要求自己设计,但是要求相关数据要存储在数据文件中。测试数据:要求使用1、全部合法数据;2、局部非法数据。进行程序测试,以保证程序的稳定。 测试数据及测试结果请在上交的资料中写明; */ #include #include #include #include #include"map.h" #define MAXN 100 #define MAXMEM 100 #define Elemtype char ============================== //树 typedef struct BiTNode { int mark;//标记 int level; char name[50];//姓名 char birthday[50];//生日 char address[MAXN];//住址

数据结构家谱课程设计报告

家谱(3-1) 一、题目要求 基本要求: 从文件中读入家庭成员建立家谱,以孩子兄弟表示法存储。基本功能: 家谱管理,如: (1)在家谱中添加新成员,并追加到文件中。 (2)输出指定家庭的所有成员。 (3)确定指定成员在家族中的辈份(第几代)。 等等。 二.概要设计 (1)功能部分: 本程序共实现了6个功能分别为: 1.读出家谱并显示 2.确定指定成员在家族中的辈份 3.输出指定辈的所有成员 4.在家谱中添加新成员,并追加到文件中 5.输出指定家庭的所有成员 6.退出本系统 (2)各功能的算法思想: 1.读出家谱并显示

存储结构用栈,按照先显示双亲,然后显示其所有孩子的顺序显示所有的家庭成员。 2.确定指定成员在家族中的辈份 用求成员所在的二叉树中的层数(按层遍历二叉树)来确定,这里采用的是递归算法 3.输出指定辈的所有成员 此处定义了一个新的结构体类型(增加存储节点所在的层数),定义如下: struct {BTNode *q; intloc;//存结点所在的层数 }qu[10]; 并用一个队列来比较显示同辈分的所有成员。 4.在家谱中添加新成员,并追加到文件中 首先,输入一个新成员的名字; 然后,输入其双亲; 之后,再添加到整个存储二叉链表中。 然后,再将新的存储结构写回到文件中。 二叉链表的结点类型为: typedefstruct node{ElemType data[10];//存放成员的名字 struct node *child;//其孩子指针 struct node *brother;//其兄弟指针

5.输出指定家庭的所有成员 首先,设一个栈,并设一个标记位,先置1; 然后,找到输入的要待显示的成员,将标记位置0; 再次,显示其孩子和兄弟,依次下去直到显示完其所有的亲戚。 6.退出本系统 通过一个输入字符q来控制,每完成一个功能,系统提示是否要继续操作: 当q为“Y”或者“y”时,显示菜单,程序继续执行; 当q为其他字符时,程序执行结束,退出本系统。 三、详细设计: 通过一个do-while语句来控制各个模块的选择和实现。 1.读出家谱并显示 void display(BTNode *b){BTNode *q[10]; //定义一个栈 int front,rear; int k; BTNode *p; p=b;k=0; front=-1;rear=0; q[rear]=p; //头结点先入栈 while(front

相关文档
最新文档