logo资料库

家谱管理系统 数据结构课设文档.doc

第1页 / 共39页
第2页 / 共39页
第3页 / 共39页
第4页 / 共39页
第5页 / 共39页
第6页 / 共39页
第7页 / 共39页
第8页 / 共39页
资料共39页,剩余部分请下载后查看
南京航空航天大学
1.问题陈述
2.所采用的数据类型与数据结构
3.算法思想
4.源程序
5.算法复杂度
6.测试数据和结果
7.总结
南京航空航天大学 数据结构课程设计 家谱管理系统 姓 名:陈学轩 学 号:161110128 班 级:1611101 指导老师:秦小麟 1
目 录 1. 问题陈述…………………………………………………………………………3 2.所采用的数据类型以及数据结构………………………………………………3 3.算法思想……………………………………………………………………………5 4 . 源 程 序 … … … … … … … … … … … … … … … … … … … … … … … … … … 5 5.算法复杂度 ………………………………………………………………………32 6.测试数据和结果 …………………………………………………………………32 7.总结……………………………………………………………………………39 2
1.问题陈述 家谱用于记录某家族历代家族成员的情况与关系。现编制一个家谱资料管理软件,实 现对一个家族所有的资料进行收集整理。支持对家谱的存储、更新、查询等操作。并用计算 机永久储存家族数据,方便随时调用。 2.所采用的数据类型与数据结构 在动手编制程序之前,先要做好程序的规划,包括程序储存数据所用的结构,数据类型 等等,只有确定了数据类型和数据结构,才能在此基础上进行各种算法的设计和程序的编写。 首先是考虑数据类型。在家谱中,家族成员是最基本的组成部分,对于家族管理中, 已经不能再进行细分了,所以选定家族成员作为数据的基本类型,并在程序中定义 Info 的 结构体。其中 Info 的各种属性可以根据需要进行添加或删除,从日常生活应用的角度出发, 制定了 Info 中包含了一下属性: char name[max_char_num];//姓名 char birthplace[max_char_num];//出生地点 Date birthdate;//结构 date 定义的出生日期 char dead[max_char_num];//是否已死亡 Date deathdate;//结构 date 定义的死亡日期 char sex[max_char_num];//性别 int height;//高度 char occupation[max_char_num];//工作职务 char education[max_char_num];//受教育程度 char top_headship[max_char_num];//最高职位 char parentname[max_char_num];//父亲姓名,用于添加节点时用 int Depth;//二叉树深度,输出二叉树时用 char love[max_char_num];//是否已婚 int N;//代数 char lname[max_char_num];//配偶姓名 3
char lbirthplace[max_char_num];//配偶出生地点 Date lbirthdate;//配偶结构 date 定义的出生日期 char ldead[max_char_num];//配偶是否已死亡 Date ldeathdate;//配偶结构 date 定义的死亡日期 char lsex[max_char_num];//配偶性别 int lheight;//配偶高度 char loccupation[max_char_num];//配偶工作职务 char leducation[max_char_num];//配偶受教育程度 char ltop_headship[max_char_num];//配偶最高职位 并用 Date 结构体定义了年月日,可有效管理人员的出生日期和死亡日期 struct Date { }; int year; int month; int day; //年 //月 //日 因为编写的为家谱管理系统,所以整体上我采用了二叉树的结构进行编写,这里运用 的是三叉链表的结构,首次添加的成员做为根节点,以此往下进行分支,在结构体中定义了 一个孩子结点,一个兄弟结点,一个双亲结点,方便各个代数之间的查询和添加,又因为把 配偶的信息与本人的信息存储在了一起,所以没有配偶的结点,查询到配偶也就查询到了本 人,但是这也造成了我无法修改配偶的信息,只能添加新的配偶信息和查看配偶的信息; typedef struct CSNode { Info data; //个人信息类型结构 CSNode *firstchild,*nextsibling,*parent; //csnode 的第一个孩子节点,下一个兄弟节点、 }*person; 双亲借点 在家族关系的表示上,我用的是代数来表示,比如最开始的为第一代,第一代的孩子 为第二代,以此类推,因为家族成员都在二叉树上,我遍历一遍二叉树后就可以知道哪个成 4
员是第几代,这样来表示哪个成员是晚辈、长辈或是平辈。 毫无疑问,用指针来处理数据的确是方便直观,但当我要储存数据是,便发现把指针 储存进去是没有作用的,因为当我们下一次读取数据的时候,数据内存地址已经不同了,不 在是我们上次存储数据时的地址,也就是说指针这时已经是没有作用了。要解决这样的问题, 我们必须要在存储数据之前,先家族树序列化,用数组(或者其他可以用数字表示关系的方 法)来存储,并且,再下一次读取数据时,再把数据按照序列号重新组成一个家族树,过程 比较繁复,而且实现起来也不容易。所以我便考虑直接用数组来存储数据,即使是在内存中 也用数组来处理数据间的联系。运用顺序表这个结构虽然不是那么直观,但在查找数据时的 算法设计比较简单容易实现,效率高,而且在内存中的数据可以直接读入到文件中,文件中 的数据也可以直接读入内存,不需要进行转换。所以在衡量的各个方面之后,我决定用数组 来处理数据间的联系。 3.算法思想 1.在保存和显示家谱时,用先序遍历家谱树再进行操作 2.在删除某一人时,则用后序遍历找到该节点并将该结点及其子节点一并删除 3.在进行查找时,用递归算法调用 FindByName()函数进行遍历家谱树 4.在进行各种查询和添加结点时,用名字进行查询时都用递归算法调用 FindByName()函 数进行查找 4.源程序 Genealogy.h 家谱类的头文件,进行家谱类中函数的定义,以及人员的数据存储类型 #define max_char_num 100 #include #include #include #include #include struct Date { int year; //年 5
int month; int day; //月 //日 }; struct Info { char name[max_char_num];//姓名 char birthplace[max_char_num];//出生地点 Date birthdate;//结构 date 定义的出生日期 char dead[max_char_num];//是否已死亡 Date deathdate;//结构 date 定义的死亡日期 char sex[max_char_num];//性别 int height;//高度 char occupation[max_char_num];//工作职务 char education[max_char_num];//受教育程度 char top_headship[max_char_num];//最高职位 char parentname[max_char_num];//父亲姓名,用于添加节点时用 int Depth;//二叉树深度,输出二叉树时用 char love[max_char_num];//是否已婚 int N;//代数 char lname[max_char_num];//配偶姓名 char lbirthplace[max_char_num];//配偶出生地点 Date lbirthdate;//配偶结构 date 定义的出生日期 char ldead[max_char_num];//配偶是否已死亡 Date ldeathdate;//配偶结构 date 定义的死亡日期 char lsex[max_char_num];//配偶性别 int lheight;//配偶高度 char loccupation[max_char_num];//配偶工作职务 char leducation[max_char_num];//配偶受教育程度 char ltop_headship[max_char_num];//配偶最高职位 }; typedef struct CSNode { //个人信息类型结构 Info data; CSNode *firstchild,*nextsibling,*parent; //csnode 的第一个孩子节点,下一个兄弟节点, 双亲借点 }*person; class GEnealogy { public: 6
GEnealogy();//构造函数 ~GEnealogy();//析构函数 void NewGEnealogy();//建立一个空的家谱树 void CreateGEnealogy();//从磁盘读取文件建立家谱树 void DestroyGEnealogy();//删除家谱树 void SaveGEnealogy(); //保存家谱树 void PreOrderTraverse(fstream &f,person& T ,void (*Visit)(fstream &f,person &T));// 先 序 遍历家谱树,为保存和显示家谱树作准备 void PostOrderTraverse(person& T,void (*Visit)(person& T));//后序遍历家谱树,为删除家 谱树作准备 void ReadNode(fstream &f,person &pnode); // 从 二 进 制 文 件 读 取 结 点 信 息 以 供 CreateGenealogy()建立家谱树 void FindByRelationship(person pnode); //按照亲属关系查找某人的父母,孩子,兄 弟,若查找成功则显示出来 int FindByRelationship2(person& T,person& Tname,char* name); //查询两人的亲属 关系 void Modify(person& pNode,person newValue);//修改某个人的信息 void ModifyData(person &pnode);//修改某人信息时输入 pnode 的个人信息 int CompareDate(Date date1, Date date2);// //比较两日期大小,若 date1 比 date2 早,返回 -1;date1 比 date2 晚,返回 1;date1 与 date2 相等,返回 0 void FindByName(person& T,person& Tname,char* name);//查找姓名=name 的人,若在 家谱中,用 Tname 返回,否则 Tname 为空,Tname 初始为空 void FindByBirthplace(person &T,person& Tname,char* name);//查找出生地=name 的人, 若在家谱中,则显示出来,否则显示出错信息,Tname 初始为空 void FindByBirthday(person &T,person& Tname,Date date);//查找出生日期=date 的人,若 在家谱中,则显示出来,否则显示出错信息,Tname 初始为空 void FindTodayBirthday(person &T);//查找今天生日的人,若在家谱中,则显示祝福信息, 7
否则显示出错信息,Tname 初始为空 void FindByDeathday(person& T,person& Tname,Date date);//查找死亡日期=date 的人, 若在家谱中,则显示出来,否则显示出错信息,Tname 初始为空 void FindBySex(person& T,person& Tname,char* name);//查找性别=name 的人,若在家 谱中,则显示出来,否则显示出错信息,Tname 初始为空 void FindByHeight(person &T,person &Tname,int height);//查找身高=height 的人,若在家 谱中,则显示出来,否则显示出错信息,Tname 初始为空 void FindByEducation(person& T,person& Tname,char* name);//查找受教育程度=name 的人,若在家谱中,则显示出来,否则显示出错信息,Tname 初始为空 void FindByOccupation(person& T,person& Tname,char* name);//查找职位=name 的人, 若在家谱中,则显示出来,否则显示出错信息,Tname 初始为空 void FindByTopHeadship(person& T,person& Tname,char* name);//查找最高职位=name 的人,若在家谱中,则显示出来,否则显示出错信息,Tname 初始为空 void Inquire();//查询函数,调用上述各个 Find 函数按成员基本信息以查询家谱 void InquireNInformation(person& T,person& Tname,int n);//查询第 N 代的所有人员信息 void Delete ( person &rootnode);//删除 rootnode 结点以及他的所有孩子结点 void Display(person info);//显示 info 的各样信息 void Displayl(person info);//显示配偶的各样信息 void Add(person parent, person addNode);//将 addnode 添加到 parent 作为 parent 的孩子结 void DisplayTree(person &pnode);//按照 depth 值在屏幕上输出整个家谱,其中只显示姓 点 名 int IsDateValid(Date date);//检查日期是否符合要求 bool IsLeapYear(int year);//判断某一年是否为闰年 person& GetRoot();//返回家谱的根结点 void InputData(person &pnode);//输入 pnode 的个人信息 8
分享到:
收藏