1、 3、统计功能3.1、统计家谱成员的总人数3.2、统计从事某种职业的人数3.3、综合统计其他功能要求:1、用文件保存家谱信息 2、图形方式显示家谱二系统总体设计(模块结构图)程序入口建立家谱读取文件保存家谱添加结点修改结点删除结点输出家谱统计基本查询关系查询祖先列表两人关系三 算法和数据结构的设计由于家族关系本身具有树的特点,所以家族关系在内存的数据结构首选为树。家庭成员之间的关系,用树形结构(家族树)表示,通过左孩子右兄弟的方式变为二叉树,创建的过程实际上就是二叉树的添加结点的过程,根据父亲的名字添加在父亲结点的左边。家谱的创建FamilyTree:FamilyTree() T=NULL;/
2、开始为空家谱 家谱结点的添加void FamilyTree:Add(person parent, person addNode) /将addnode添加到parent作为parent的孩子结点 int n=0; addNode-firstchild=addNode-nextsibling=NULL; /初始时firstchild同nextsibling都为空 parent=parent; if(parent=NULL) /如果父结点空 if(T=NULL) /如果根结点空 addNode-data.Depth=n; T=addNode; /将addnode赋给根结点 return; n=T-d
3、ata.Depth+1;/否则将原来的根结点成为新根结点的孩子 T- /并使原来根结点的depth值加1 firstchild=T;parent=addNode; strcpy(addNode-data.parentname,parent-data.name); n=parent-/将depth值加1 if(parent-firstchild=NULL) /如果parent无孩子,把addNode加入其firstchild parent-firstchild=addNode; else InsertSibling(parent-firstchild,addNode); /否则插入到相应的兄弟结
4、点中去 家谱结点的修改就是将结点的指针传入,更新数据就可完成,代码如下:Modify(person &curnode,person newnode) /修改某个人的信息 strcpy(curnode-data.name,newnode-data.birthplace,newnode-data.birthplace);data.sex,newnode-data.sex);data.occupation,newnode-data.occupation);data.education,newnode-data.education);data.top_headship,newnode-data.top
5、_headship); curnode-data.height=newnode-data.height;data.birthdate=newnode-data.birthdate;data.deathdate=newnode-data.deathdate;家谱结点的删除是删除该结点及这个结点对应的所有孩子结点的信息,释放内存空间就可完成,代码如下:Delete(person &rootNode) /删除rootnode结点以及他的所有孩子结点 if(rootNode-parent) /rootnode不是根结点 parent-firstchild=rootNode)/如果rootnode为其父
6、结点的第一个孩子 rootNode-firstchild=rootNode-nextsibling; /将rootnode的nextsibling结点变为rootnodeparent结点的firstchild结点 person p=rootNode-firstchild; /否则,找到rootnode在兄弟中的位置 for(;p-nextsibling!=rootNode;p=p-nextsibling) ; p-nextsibling=rootNode- /插入到兄弟中 PostOrderTraverse(rootNode-firstchild,DestroyNode);/调用后序遍历删除r
7、ootnode的所有孩子结点 if(rootNode=T) /删除rootnode结点 DestroyNode(T); DestroyNode(rootNode);家谱信息的存储是按先序遍历的方式依次存入硬盘的,读取的时候,将第一个结点的信息对应根结点,后面依次根据父亲的姓名使用插入函数完成家谱的重建,代码如下:SaveFamilyTree() /保存二叉树到文件 fstream f(1.dat,ios:binary|ios:out);/以二进制写方式打开文件 if(!f) cerrfirstchild,Visit);nextsibling,Visit);后序遍历:PostOrderTrave
8、rse(person &T,void (_cdecl *Visit)(person & /后序遍历二叉树,并执行visit函数 PostOrderTraverse(T- (*Visit)(T);成员的查找查找部分涉及的查找方法多样,这里用按姓名查找来代表,其他查找使用的算法思想是类似的,使用递归的方法,代码如下:FindByName(person& T,person& Tname,char* name)/search the name in info from root T /查找姓名name的人,若在家谱中,用Tname返回,否则Tname为空,Tname初始为空 if(strcmp(T-d
9、ata.name,name)=0) /用string库的strcmp()比较两个字符串,若相等,则找到符合条件的 Tname=T; else FindByName(T-firstchild,Tname,name); /对T的firstchild递归搜索 nextsibling,Tname,name); /对T的nextsibling递归搜索 四 程序测试及结果分析程序在VC里编译连接运行以后,显示主界面如下:选择相应的操作数,以回车键结束。例如 新建家谱时,出现如下界面,按提示输入各种信息。添加成员,类似界面,按照操作提示输入家谱成员信息。载入家谱:显示家谱所有信息:删除彭了及其子孙后的结果如
10、下:删除成功。重新保存家谱并退出:退出后再进入,显示家谱所有成员信息,可以看出文件已经被保存。经过测试,功能都已实现。五 复杂度分析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) O(n)7) PreOrderTraverse(fstream &T) O(n)8) SaveNode(fstream &f, person &
11、pnode) O(1)9) SaveFamilyTree() O(n)10) ReadNode(fstream &11) FindByName(person& Tname,char* name) O(n)12) FindByBirthplace(person& Tname,char* birthplace) O(n)13) FindByBirthday(person& Tname,Date day1) O(n)14) FindByDeathday(person& Tname,Date day1) O(n)15) FindBySex(person& Tname,char *sex) O(n)16
12、) FindByHeight(person& Tname,int h) O(n)17) FindByAddress(person& Tname,char* address) O(n)18) FindByEducation(person& Tname,char* edu) O(n)19) FindByOccupation(person& Tname,char* job) O(n)20) FindByTopHeadship(person& Tname,char* top) O(n)21) AddOperation() O(1)22) Display(person info) O(1)23) IsD
13、ateValid(Date date) O(1)24) CompareDate(Date date1, Date date2) O(1)25) IsLeapYear(int year) O(1)26) InsertSibling(person& firstchild,person insertsibling) O(1)27) Delete(person &rootNode) O(n)28) Modify(person &curnode,person newnode) O(1)29) DisplayTree(person &T) O(n)30) Add(person parent, person
14、 addNode) O(1)31) FindByRelationship(person pnode) O(n)32) Ancestor(person pnode) O(1)33) Relationship(person pnode1,person pnode2) O(n)34) InputData(person &35) InputDate(Date &day) O(1)36) Age(person pNode) O(1)37) Height(person pNode) O(1)38) AverageLife(person &T,int &personNums,int &age) O(n)39
15、) AverageHeight(person &T, int &personNums, int &height) O(n)40) MaleFemale(person&maleNum,int &femaleNum) O(n)41) FamilyNumber(person pnode) O(1)42) TotalFamilyNumber(person &totalfamily) O(n)43) TotalFamily(person &total) O(n)44) GetRoot() O(1)六 源程序Gneealogy.h#define max_char_num 100 #define max_a
16、rray_num 30 /5个include#include stdio.hiostream.hiostreamstdlib.hstring.hfstream.hcstdlibwindows.hstruct Date int year; /年 int month; /月 int day; /日 ;struct Info char namemax_char_num;/姓名 char birthplacemax_char_num;/出生地点 Date birthdate;/结构date定义的出生日期 Date deathdate;/结构date定义的死亡日期 char sexmax_char_nu
17、m;/性别 char wife_or_husbandmax_char_num;/配偶 char phonemax_array_num;/电话 char addressmax_char_num;/家庭住址 char resumemax_char_num;/简历 /其他信息如下 int height;/高度 char occupationmax_char_num;/职业 char educationmax_char_num;/受教育程度 char top_headshipmax_char_num;/最高职位 char parentnamemax_char_num;/父亲姓名,用于添加节点时用 in
18、t Depth;/二叉树深度,输出二叉树时用 typedef struct CSNode Info data; /个人信息类型结构 CSNode *firstchild,*nextsibling,*parent; /csnode的第一个孩子节点,下一个兄弟节点,双亲节点*person;class FamilyTree public: FamilyTree();/构造函数 FamilyTree();/析构函数 void NewFamilyTree();/建立一个空的家谱树 void CreateFamilyTree();/从磁盘读取文件建立家谱树 void DestroyFamilyTree()
19、;/删除家谱树 void SaveFamilyTree(); /保存家谱树 void PreOrderTraverse(fstream &f,person& T ,void (*Visit)(fstream &T);/先序遍历家谱树,为保存和显示家谱树作准备 void PostOrderTraverse(person& T,void (*Visit)(person& T);/后序遍历家谱树,为删除家谱树作准备 void ReadNode(fstream &pnode); /从二进制文件读取结点信息以供Create FamilyTree()建立家谱树 void FindByRelationshi
20、p(person pnode); /按照亲属关系查找某人的父母,孩子,兄弟,若查找成功则显示出来 void Modify(person& pNode,person newValue);/修改某个人的信息 int CompareDate(Date date1, Date date2);/ /比较两日期大小,若date1比date2早,返回-1;date1比date2晚,返回1;date1与date2相等,返回0 void FindByName(person& Tname,char* name);/查找姓名name的人,若在家谱中,用Tname返回,否则Tname为空,Tname初始为空 void
21、 FindByBirthplace(person &T,person&/查找出生地name的人,若在家谱中,则显示出来,否则显示出错信息,Tname初始为空 void FindByBirthday(person & Tname,Date date);/查找出生日期date的人,若在家谱中,则显示出来,否则显示出错信息,Tname初始为空 void FindByDeathday(person&/查找死亡日期date的人,若在家谱中,则显示出来,否则显示出错信息,Tname初始为空 void FindBySex(person&/查找性别name的人,若在家谱中,则显示出来,否则显示出错信息,Tna
22、me初始为空 void FindByHeight(person &T,person &Tname,int height);/查找身高height的人,若在家谱中,则显示出来,否则显示出错信息,Tname初始为空 void FindByEducation(person&/查找受教育程度name的人,若在家谱中,则显示出来,否则显示出错信息,Tname初始为空 void FindByOccupation(person&/查找职位name的人,若在家谱中,则显示出来,否则显示出错信息,Tname初始为空 void FindByTopHeadship(person&/查找最高职位name的人,若在家谱中,则显示出来,否则显示出错信息,Tname
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1