课程设计——《家谱管理系统》(含源码)

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;i<(*root)->record.cnt;i++) {
    	if( 找到对应节点) {
    		删除该节点;
			return ;
		}	
	}
	for(int i =0;i<(*root)->record.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;i<root->record.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<cnt){
		出队;
输出信息;
入队;
	}
}

(6)输出文件:

        a、打开指定的文件,用于写入家谱信息。

        b、使用广度优先遍历的方式,将家谱信息按一定格式写入文件。

        c、关闭文件。

void WriteToFile(Node* root) {
	打开文件;
	while(i<cnt){
		写入文件;
	}
	关闭文件;
}

4.2 调试

主菜单:

图4-2.1《家谱管理系统》调试图1

文件读取记录:

图4-2.2《家谱管理系统》调试图2

添加家谱记录:

图4-2.3《家谱管理系统》调试图3

图4-2.4《家谱管理系统》调试图4

删除家谱记录:

图4-2.5《家谱管理系统》调试图5

查询家族成员信息:

图4-2.6《家谱管理系统》调试图6

广度优先输出家谱信息:

图4-2.7《家谱管理系统》调试图7

文件输出:

图4-2.8《家谱管理系统》调试图8

图4-2.9《家谱管理系统》调试图9

5.课程设计总结

        这道题目我考虑了使用树结构来表示家谱关系,并选择了适当的数据结构来存储和管理家族成员的信息。我使用了节点结构来表示每个家庭成员。我还设计了相应的算法来实现文件读取、添加记录、删除记录、查询成员信息以及不同遍历方式下的家谱信息输出。在设计完成后,我根据算法和数据结构的设计开始编写代码。我使用C语言作为主要编程语言。在编写过程中,我注重代码的可读性和模块化,将功能拆分成独立的函数,并进行适当的参数传递和返回值处理。

        完成代码编写后,我进行了系统的调试和测试。我逐个功能模块进行测试,确保每个功能都能正常运行并返回正确的结果。我使用了不同的测试数据和边界情况来验证代码的健壮性和正确性。

        完成课程设计是一个循序渐进的过程。这个过程不仅提升了我的编程能力和算法设计能力,还培养了我解决问题和文档编写的能力。

6、附录代码

https://download.csdn.net/download/m0_73059486/88643259icon-default.png?t=N7T8https://download.csdn.net/download/m0_73059486/88643259

  • 49
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值