课程设计 |
您所在的位置:网站首页 › 用户管理系统课程设计 › 课程设计 |
1. [问题描述]
一个家谱关系由若干家谱记录构成,每个家谱记录由父亲、母亲和子女姓名构成,其中姓名是关键字。设计并实现一个简单的家谱管理系统 [任务要求] 定义一个主菜单,界面友好,演示程序以用户和计算机的对话方式进行,可以反复操作,方便用户实现下述操作。具体功能要求: (1)从键盘输入家谱记录(按照祖先到子孙的顺序输入,即第一个输入的记录的父亲域为所有人的祖先),建立家族关系树,并存储到外部文件MyFamily+ (2)学号后三位.txt(如,MyFamily001.txt)中 (3)实现家族成员的添加、删除功能。 (4)可以查询家族成员的双亲、祖先、兄弟、孩子和后代等信息。 (5)按某种顺序输出家谱信息 (树的遍历操作)、以树型结构输出家谱资料等功能。 选做: (7)通过读取外部*.txt 文件,建立家族关系树: (8)添加和删除后的结果同步到外部文件。 2. 功能和原始数据 2.1 主要功能(1)文件读取记录:从文件中读取已有的家谱记录。将读取的记录添加到家谱管理系统中,建立家族关系树。 (2)添加家谱记录:通过键盘输入,添加新的家谱记录。确定新成员的父节点,将其添加到家谱管理系统中,更新家族关系树。 (3)删除家谱记录:根据指定的成员姓名,从家谱管理系统中删除该成员及其所有后代。更新家族关系树,重新组织家谱信息。 (4)查询家族成员信息:根据成员姓名,在家谱管理系统中查询该成员的信息。输出成员的双亲、祖先、兄弟和孩子等相关信息。 (5)深度优先输出家谱信息:使用深度优先搜索算法,输出家族成员的信息。即通过不断遍历某节点的孩子,实现所有信息的输出。 (6)广度优先输出家谱信息:使用广度优先搜索算法,按照树的层级顺序遍历家谱关系树。从根节点开始,逐层输出家族成员的信息,展示家谱资料。 (7)文件输出:将家谱信息输出到文件中,以便进行永久保存或与他人共享。将家族成员的信息按照一定格式写入文件,以便后续读取和使用。 2.2 原始数据文件读取记录:文件数据如下所示,第一行数据表示数据总数;以下的每一行表示 父亲,母亲,孩子 的姓名。以下数据将作为整个系统的初始化数据: 8 张三 李四 王五 王五 小明 小红 小红 小刘 小李 小李 小黄 小孙 王五 小明 小蓝 小蓝 小绿 小紫 小孙 小可 小溪 小紫 小彭 小王 3. 程序总体设计 3.1 数据结构设计 // 家谱记录结构体 typedef struct { char father[MAX_NAME_LENGTH]; // 父亲姓名 char mother[MAX_NAME_LENGTH]; // 母亲姓名 char child[20][MAX_NAME_LENGTH]; // 孩子姓名数组 int cnt; // 孩子数量 } FamilyRecord; // 家谱节点结构体 typedef struct node { FamilyRecord record; // 家谱记录 struct node* children[200]; // 孩子节点指针数组 } Node; 3.2 程序总体框架(1)主函数:程序的入口,负责初始化系统和接收用户输入。通过菜单选择,调用相应的函数完成用户需求。 (2)文件读取记录函数:负责从文件中读取已有的家谱记录。将读取的记录添加到家谱管理系统中,建立家族关系树。 (3)添加家谱记录函数(insertRecord):负责接收用户输入,添加新的家谱记录。确定新成员的节点,将其添加到家谱管理系统中,更新家族关系树。 (4)删除家谱记录函数(deleteRecord):负责接收用户输入,删除指定的家谱记录。根据成员姓名,从家谱管理系统中删除该成员及其所有后代。更新家族关系树,重新组织家谱信息。 (5)查询家族成员信息函数(findNode):负责接收用户输入,查询家族成员的信息。根据成员姓名,在家谱管理系统中查询该成员的信息。输出成员的双亲、兄弟和孩子等相关信息。 (6)广度优先输出家谱信息函数(printFamilyTree_layer):负责按照广度优先搜索算法的顺序遍历家谱关系树。从根节点开始,逐层输出家族成员的信息,以树型结构展示家谱资料。 (7)文件输出函数(WriteToFile):负责将家谱信息输出到文件中,以便进行永久保存或与他人共享。将家族成员的信息按照一定格式写入文件。 3.3 函数原型清单 // 函数声明 Node* createNode(FamilyRecord record); // 创建家谱节点 bool insertRecord(Node** root, FamilyRecord record); // 插入家谱记录 void deleteRecord(Node** root, const char* name); // 删除家谱记录 Node* findNode(Node* root, const char* name); // 查找家谱节点 void printFamily(Node* node); // 输出家族成员的家谱信息 void printFamilyTree_layer(Node* root); // 广度优先输出家谱信息 void WriteToFile(Node* root); // 将家谱信息写入文件 void destroyFamilyTree(Node* root); // 销毁家族关系树 void readFromFile(Node** familyTree); // 从文件中读取家谱信息 3.4 程序组织图3-4 《家谱管理系统》程序菜单图 4. 功能算法设计和调试 4.1 主要功能算法设计图4-1 函数调用图 (1)文件读取记录:a、打开指定的文件。 b、逐行读取文件内容。 c、解析每行记录,提取双亲和孩子姓名。 d、调用添加家谱记录函数,将读取到的记录添加到家谱管理系统中。 e、关闭文件。 void readFromFile(Node** familyTree) { 打开文件; while(n--){ 读取信息; } 关闭文件; } (2)添加家谱记录:a、创建一个新的家族对象,并为其分配内存。 b、设置新成员的信息。 c、根据节点信息找到父节点对象。 d、将新成员添加为父节点的子节点。 e、更新家谱管理系统中的树结构。 bool insertRecord(Node** root, FamilyRecord record) { if (*root == NULL) { 创建节点。 return true; } else if(找到对应节点) { 将孩子添加到该节点; } } (3)删除家谱记录:a、根据给定的姓名,在家谱管理系统中查找该成员。 b、如果找到成员,将该成员节点设为空。 c、删除该成员的对象并释放内存。 void deleteRecord(Node** root, const char* name) { if (*root == NULL) { return; } for(int i =0;irecord.cnt;i++) { if( 找到对应节点) { 删除该节点; return ; } } for(int i =0;irecord.cnt;i++) { if((*root)->children[i] != NULL) { 递归调用deleteRecord(); } } return ; } (4)查询家族成员信息:a、根据给定的姓名,在家谱管理系统中查找该成员。 b、如果找到成员,输出该成员的双亲、孩子等相关信息。 Node* findNode(Node* root, const char* name) { if (root == NULL) { return NULL; } for(int i =0;irecord.cnt;i++){ if(找到该节点) return root; Node* r =递归调用findNode(); if(r!=NULL) return r; } return NULL; } (5)广度优先输出家谱信息:a、使用队列数据结构,从根节点开始进行广度优先遍历。 b、将根节点入队。 c、循环遍历队列,每次出队一个节点并输出其信息。 d、将出队节点的子节点入队。 e、直到队列为空,遍历结束。 void printFamilyTree_layer(Node* root) { 新建队列; while(i |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |