数据结构课设报告.docx

上传人:b****5 文档编号:6406070 上传时间:2023-01-06 格式:DOCX 页数:56 大小:290.54KB
下载 相关 举报
数据结构课设报告.docx_第1页
第1页 / 共56页
数据结构课设报告.docx_第2页
第2页 / 共56页
数据结构课设报告.docx_第3页
第3页 / 共56页
数据结构课设报告.docx_第4页
第4页 / 共56页
数据结构课设报告.docx_第5页
第5页 / 共56页
点击查看更多>>
下载资源
资源描述

数据结构课设报告.docx

《数据结构课设报告.docx》由会员分享,可在线阅读,更多相关《数据结构课设报告.docx(56页珍藏版)》请在冰豆网上搜索。

数据结构课设报告.docx

数据结构课设报告

《数据结构》课程设计报告

题目:

简易电子家谱系统的设计与实现

姓名:

涂雯

学号:

U200814434

班级:

0806

专业:

计算机科学与技术

报告日期:

2010年9月18日

一.问题描述

问题背景

家谱是记载同一姓氏血缘关系的世系、重要人物、个人事迹、家族历史为主要内容的谱籍,又称“族谱”、“家谱”、“家乘”,还有称作“谱碟”。

家谱上可以追本溯源,缅怀先人,下可以辨明关系,联络宗亲,从而启孝梯心,唤德善之本,激励后人,奋发有为,其作用不可尽述。

在社会方面,家谱对于海内外华人寻根认祖,增强民族凝聚力起着重要作用。

在文史工作者,家谱是研究人口学、社会学、经济学、历史学、氏族学、人物传记,以及研究地方史乃是重要资料。

在个人方面家谱又是每个公民身份证明之一。

问题内容:

用树形的形式表示某家族的家谱,每个树结点表示一个家族成员,成员基本信息如下,具体属性自行确定。

1、姓名

2、性别

3、出生地

4、配偶

5、电话

6、家庭住址

7、职业

8、简历

9、其他

系统实现功能:

1、家谱信息

1.1、输入

1.2、修改

1.3、删除

2、查询

2.1、某家谱成员的所有子孙的集合

2.2、某家谱成员的所有祖先的集合

2.3、某家谱成员的所有同辈成员的集合

2.4、求某家谱成员的所有上一辈成员的集合

2.5、给出两个家谱成员,确定他们的关系

2.6、其他查询

3、统计功能

3.1、统计家谱成员的总人数

3.2、统计从事某种职业的人数

3.3、综合统计

其他功能

要求:

1、用文件保存家谱信息

2、图形方式显示家谱

二.系统总体设计(模块结构图)

程序入口

建立家谱

读取文件

保存家谱

添加结点

修改结点

删除结点

输出家谱

统计

基本查询

关系查询

祖先列表

两人关系

 

三.算法和数据结构的设计

由于家族关系本身具有树的特点,所以家族关系在内存的数据结构首选为树。

家庭成员之间的关系,用树形结构(家族树)表示,通过左孩子右兄弟的方式变为二叉树,创建的过程实际上就是二叉树的添加结点的过程,根据父亲的名字添加在父亲结点的左边。

家谱的创建

FamilyTree:

:

FamilyTree()

{

T=NULL;//开始为空家谱

}

家谱结点的添加

voidFamilyTree:

:

Add(personparent,personaddNode)

{

//将addnode添加到parent作为parent的孩子结点

intn=0;

addNode->firstchild=addNode->nextsibling=NULL;//初始时firstchild同nextsibling都为空

addNode->parent=parent;

if(parent==NULL)//如果父结点空

{

if(T==NULL)//如果根结点空

{

addNode->data.Depth=n;

T=addNode;//将addnode赋给根结点

return;

}

n=T->data.Depth+1;//否则将原来的根结点成为新根结点的孩子

T->data.Depth=n;//并使原来根结点的depth值加1

addNode->firstchild=T;

T->parent=addNode;

T=addNode;

return;

}

strcpy(addNode->data.parentname,parent->data.name);

n=parent->data.Depth+1;

addNode->data.Depth=n;//将depth值加1

if(parent->firstchild==NULL)//如果parent无孩子,把addNode加入其firstchild

parent->firstchild=addNode;

else

InsertSibling(parent->firstchild,addNode);//否则插入到相应的兄弟结点中去

}

家谱结点的修改就是将结点的指针传入,更新数据就可完成,代码如下:

voidFamilyTree:

:

Modify(person&curnode,personnewnode)

{

//修改某个人的信息

strcpy(curnode->data.name,newnode->data.name);

strcpy(curnode->data.birthplace,newnode->data.birthplace);

strcpy(curnode->data.sex,newnode->data.sex);

strcpy(curnode->data.occupation,newnode->data.occupation);

strcpy(curnode->data.education,newnode->data.education);

strcpy(curnode->data.top_headship,newnode->data.top_headship);

curnode->data.height=newnode->data.height;

curnode->data.birthdate=newnode->data.birthdate;

curnode->data.deathdate=newnode->data.deathdate;

}

家谱结点的删除是删除该结点及这个结点对应的所有孩子结点的信息,释放内存空间就可完成,代码如下:

voidFamilyTree:

:

Delete(person&rootNode)

{

//删除rootnode结点以及他的所有孩子结点

if(rootNode->parent)//rootnode不是根结点

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

rootNode->parent->firstchild=rootNode->nextsibling;//将rootnode的nextsibling结点变为rootnodeparent结点的firstchild结点

else

{

personp=rootNode->parent->firstchild;//否则,找到rootnode在兄弟中的位置

for(;p->nextsibling!

=rootNode;p=p->nextsibling)

;

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

}

PostOrderTraverse(rootNode->firstchild,DestroyNode);//调用后序遍历删除rootnode的所有孩子结点

if(rootNode==T)//删除rootnode结点

DestroyNode(T);

else

DestroyNode(rootNode);

}

家谱信息的存储是按先序遍历的方式依次存入硬盘的,读取的时候,将第一个结点的信息对应根结点,后面依次根据父亲的姓名使用插入函数完成家谱的重建,代码如下:

voidFamilyTree:

:

SaveFamilyTree()

{

//保存二叉树到文件

fstreamf("1.dat",ios:

:

binary|ios:

:

out);//以二进制写方式打开文件

if(!

f)

{

cerr<<"文件打开失败!

"<

return;

}

PreOrderTraverse(f,T,SaveNode);//调用先序遍历写二叉树信息到文件

f.close();//关闭文件

//person&t=FamilyTree:

:

GetRoot();//返回家谱的根结点

//returnt;

}

家谱信息的遍历

主要使用递归的方式遍历家谱树,代码入下:

先序遍历:

voidFamilyTree:

:

PreOrderTraverse(fstream&f,person&T,void(__cdecl*Visit)(fstream&f,person&T))

{

//先序遍历二叉树,并执行visit函数

if(T)

{

(*Visit)(f,T);

PreOrderTraverse(f,T->firstchild,Visit);

PreOrderTraverse(f,T->nextsibling,Visit);

}

}

后序遍历:

voidFamilyTree:

:

PostOrderTraverse(person&T,void(__cdecl*Visit)(person&T))

{

//后序遍历二叉树,并执行visit函数

if(T)

{

PostOrderTraverse(T->firstchild,Visit);

PostOrderTraverse(T->nextsibling,Visit);

(*Visit)(T);

}

}

成员的查找

查找部分涉及的查找方法多样,这里用按姓名查找来代表,其他查找使用的算法思想是类似的,使用递归的方法,代码如下:

voidFamilyTree:

:

FindByName(person&T,person&Tname,char*name)//searchthenameininfofromrootT

{

//查找姓名=name的人,若在家谱中,用Tname返回,否则Tname为空,Tname初始为空

if(T)

{

if(strcmp(T->data.name,name)==0)//用string库的strcmp()比较两个字符串,若相等,则找到符合条件的

Tname=T;

else

{

FindByName(T->firstchild,Tname,name);//对T的firstchild递归搜索

FindByName(T->nextsibling,Tname,name);//对T的nextsibling递归搜索

}

}

}

四.程序测试及结果分析

程序在VC里编译连接运行以后,显示主界面如下:

选择相应的操作数,以回车键结束。

例如新建家谱时,出现如下界面,按提示输入各种信息。

添加成员,类似界面,按照操作提示输入家谱成员信息。

载入家谱:

显示家谱所有信息:

删除彭了及其子孙后的结果如下:

删除成功。

重新保存家谱并退出:

退出后再进入,显示家谱所有成员信息,可以看出文件已经被保存。

经过测试,功能都已实现。

五.复杂度分析

1)NewFamilyTree()O

(1)

2)FamilyTree()O

(1)

3)CreateFamilyTree()O(n)

4)DestroyNode(person&pnode)O

(1)

5)DestroyFamilyTree()O(n)

6)PostOrderTraverse(person&T,void(__cdecl*Visit)(person&T))O(n)

7)PreOrderTraverse(fstream&f,person&T,void(__cdecl*Visit)(fstream&f,person&T))O(n)

8)SaveNode(fstream&f,person&pnode)O

(1)

9)SaveFamilyTree()O(n)

10)ReadNode(fstream&f,person&pnode)O

(1)

11)FindByName(person&T,person&Tname,char*name)O(n)

12)FindByBirthplace(person&T,person&Tname,char*birthplace)O(n)

13)FindByBirthday(person&T,person&Tname,Dateday1)O(n)

14)FindByDeathday(person&T,person&Tname,Dateday1)O(n)

15)FindBySex(person&T,person&Tname,char*sex)O(n)

16)FindByHeight(person&T,person&Tname,inth)O(n)

17)FindByAddress(person&T,person&Tname,char*address)O(n)

18)FindByEducation(person&T,person&Tname,char*edu)O(n)

19)FindByOccupation(person&T,person&Tname,char*job)O(n)

20)FindByTopHeadship(person&T,person&Tname,char*top)O(n)

21)AddOperation()O

(1)

22)Display(personinfo)O

(1)

23)IsDateValid(Datedate)O

(1)

24)CompareDate(Datedate1,Datedate2)O

(1)

25)IsLeapYear(intyear)O

(1)

26)InsertSibling(person&firstchild,personinsertsibling)O

(1)

27)Delete(person&rootNode)O(n)

28)Modify(person&curnode,personnewnode)O

(1)

29)DisplayTree(person&T)O(n)

30)Add(personparent,personaddNode)O

(1)

31)FindByRelationship(personpnode)O(n)

32)Ancestor(personpnode)O

(1)

33)Relationship(personpnode1,personpnode2)O(n)

34)InputData(person&pnode)O

(1)

35)InputDate(Date&day)O

(1)

36)Age(personpNode)O

(1)

37)Height(personpNode)O

(1)

38)AverageLife(person&T,int&personNums,int&age)O(n)

39)AverageHeight(person&T,int&personNums,int&height)O(n)

40)MaleFemale(person&T,int&maleNum,int&femaleNum)O(n)

41)FamilyNumber(personpnode)O

(1)

42)TotalFamilyNumber(person&T,int&totalfamily)O(n)

43)TotalFamily(person&T,int&total)O(n)

44)GetRoot()O

(1)

六.源程序

Gneealogy.h

#definemax_char_num100

#definemax_array_num30

//5个include

#include

#include

#include

#include

#include

#include

#include

#include

#include

 

structDate

{

intyear;//年

intmonth;//月

intday;//日

};

structInfo

{

charname[max_char_num];//姓名

charbirthplace[max_char_num];//出生地点

Datebirthdate;//结构date定义的出生日期

Datedeathdate;//结构date定义的死亡日期

charsex[max_char_num];//性别

charwife_or_husband[max_char_num];//配偶

charphone[max_array_num];//电话

charaddress[max_char_num];//家庭住址

charresume[max_char_num];//简历

//其他信息如下

intheight;//高度

charoccupation[max_char_num];//职业

chareducation[max_char_num];//受教育程度

chartop_headship[max_char_num];//最高职位

charparentname[max_char_num];//父亲姓名,用于添加节点时用

intDepth;//二叉树深度,输出二叉树时用

};

typedefstructCSNode

{

Infodata;//个人信息类型结构

CSNode*firstchild,*nextsibling,*parent;//csnode的第一个孩子节点,下一个兄弟节点,双亲节点

}*person;

classFamilyTree

{

public:

FamilyTree();//构造函数

~FamilyTree();//析构函数

voidNewFamilyTree();//建立一个空的家谱树

voidCreateFamilyTree();//从磁盘读取文件建立家谱树

voidDestroyFamilyTree();//删除家谱树

voidSaveFamilyTree();//保存家谱树

voidPreOrderTraverse(fstream&f,person&T,void(*Visit)(fstream&f,person&T));//先序遍历家谱树,为保存和显示家谱树作准备

voidPostOrderTraverse(person&T,void(*Visit)(person&T));//后序遍历家谱树,为删除家谱树作准备

voidReadNode(fstream&f,person&pnode);//从二进制文件读取结点信息以供CreateFamilyTree()建立家谱树

voidFindByRelationship(personpnode);//按照亲属关系查找某人的父母,孩子,兄弟,若查找成功则显示出来

voidModify(person&pNode,personnewValue);//修改某个人的信息

intCompareDate(Datedate1,Datedate2);////比较两日期大小,若date1比date2早,返回-1;date1比date2晚,返回1;date1与date2相等,返回0

voidFindByName(person&T,person&Tname,char*name);//查找姓名=name的人,若在家谱中,用Tname返回,否则Tname为空,Tname初始为空

voidFindByBirthplace(person&T,person&Tname,char*name);//查找出生地=name的人,若在家谱中,则显示出来,否则显示出错信息,Tname初始为空

voidFindByBirthday(person&T,person&Tname,Datedate);//查找出生日期=date的人,若在家谱中,则显示出来,否则显示出错信息,Tname初始为空

voidFindByDeathday(person&T,person&Tname,Datedate);//查找死亡日期=date的人,若在家谱中,则显示出来,否则显示出错信息,Tname初始为空

voidFindBySex(person&T,person&Tname,char*name);//查找性别=name的人,若在家谱中,则显示出来,否则显示出错信息,Tname初始为空

voidFindByHeight(person&T,person&Tname,intheight);//查找身高=height的人,若在家谱中,则显示出来,否则显示出错信息,Tname初始为空

voidFindByEducation(person&T,person&Tname,char*name);//查找受教育程度=name的人,若在家谱中,则显示出来,否则显示出错信息,Tname初始为空

voidFindByOccupation(person&T,person&Tname,char*name);//查找职位=name的人,若在家谱中,则显示出来,否则显示出错信息,Tname初始为空

voidFindByTopHeadship(person&T,person&Tname,char*name);//查找最高职位=name的人,若在家谱中,则显示出来,否则显示出错信息,Tname

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1