家谱管理系统的设计与实现(附源码)

发布时间:2024年01月06日

目录

1. 题目

2. 系统功能分析

2.1. 系统功能

2.2. 功能详细说明

2.2.1. 读取文件

2.2.2. 添加孩子

2.2.3. 删除名字

2.2.4. 查找

3. 程序源码

4. 运行截图


1. 题目

1、问题描述

家谱管理系统是查询家谱信息必不可少的一部分,利用家谱管理系统可以清楚地查询成员的详细信息。成员的信息包括:姓名(假设姓名不重复)、出生年月日、目前状况(健在、身故)。请设计合理的数据结构存储该家谱的信息,要求能够实现以下功能功能。

2、基本功能

该系统应具有以下功能(即可以重复操作):

家谱信息预先设置好,程序启动,从文件中读入家谱信息,自动建立家谱数据结构,使用菜单实现以下功能,每次操作后应该输出当前结果:

(1)插入:给某个人添加一个孩子

(2)删除:删除某个人,如果某人有后代,不允许删除

(3)堂兄弟:根据所在世代的字,可以输出该世代所有人的信息

(4)父子:可以根据姓名查询,并输出该人的父亲和孩子信息

(5)显示:以凹入表的形式显示家谱

(6)退出时,家谱信息保存到文件中

3、测试数据

2. 系统功能分析

2.1. 系统功能

2.2. 功能详细说明

2.2.1. 读取文件

通过循环将家谱信息读入家谱树。

2.2.2. 添加孩子

2.2.3. 删除名字

2.2.4. 查找

3. 程序源码

#include <stdlib.h>  
#include<iostream>
#include<fstream>
#pragma warning(disable:4996)
using namespace std;
typedef struct {
char name[50];//姓名
int brithday;//出生
int beifen;//辈分
int die;//是否健在
}StructNode;
typedef struct Node {
StructNode data;
struct Node* lc;//左指针
struct Node* rc;//右指针
}TreeNode;

int num;//总人数

TreeNode* root;//根指针
TreeNode* findLocation(TreeNode* b, char cname[]) //查询位置
{
    TreeNode* p;
    if (b == NULL)   return NULL;
    if (strcmp(b->data.name, cname) == 0)
        return b;
    if (b->lc) {
        p = findLocation(b->lc, cname);
        if (p)return p;
    }
    if (b->rc) {
        p = findLocation(b->rc, cname);
        if (p)return p;
    }

    return NULL;
}
void searchByChar(TreeNode* node, char letter) {
    if (node == NULL) {
        return;
    }
    string name = node->data.name;
    if (name.find(letter) != string::npos) {
        cout << "Name: " << node->data.name << endl;
        cout << "Birthday: " << node->data.brithday << endl;
        cout << "Alive: " << node->data.die << endl;
        cout << "----------------" << endl;
    }
    searchByChar(node->lc, letter);
    searchByChar(node->rc, letter);
}

TreeNode* creatFirst()//创建你的祖宗
{
    TreeNode* p;
    p = new Node;//创建新的节点
    cout << "输入祖宗名字:" << endl;
    cin >> p->data.name;
    cout << "输入祖宗的诞生时间:" << endl;
    cin >> p->data.brithday;
    cout << "是否存活:" << endl;
    cin >> p->data.die;

    p->lc = p->rc = NULL;//左右子树清空
    p->data.beifen = 1;//当前辈分为1
    cout << "祖宗创建成功" << endl;
    return p;

}
TreeNode* creatNode()//创建一个新的节点
{
    int flag = 0;
    TreeNode* m = NULL;//指针初始化
    TreeNode* p;
    p = new Node;//创建新的节点
    cout << "输入名字:" << endl;
    cin >> p->data.name;
    m = findLocation(root, p->data.name);//查找当前名字返回的变量
    if (m != NULL)
    {
        cout << "出现重名!!!\n";
        p = NULL;
        return p;
    }
    else {

        cout << "输入诞生时间:" << endl;
        cin >> p->data.brithday;
        cout << "是否存活:" << endl;
        cin >> p->data.die;

        return p;
    }
}

void cunru(TreeNode* p, char name[], int dai, int brithday, int die)//存入结构体
{
	//赋值给结构体
	p->data.beifen = dai;
	strcpy_s(p->data.name, name);

	p->data.brithday = brithday;
	p->data.die = die;

	//显示文件的东西
	cout << "辈分:" << p->data.beifen << "  ";
	cout << "名字:" << p->data.name << "  ";

	cout << "出生:" << p->data.brithday << "  ";
	cout << "是否存活 0否1是:" << p->data.die << endl;

}
void find_Function(TreeNode* p, char name[]) //查找功能
{
	p = findLocation(p, name);
	if (p == NULL) {
		cout << "当前为空节点" << endl;
	}
	else {


		cout << "辈分:" << p->data.beifen << "  ";
		cout << "姓名:" << p->data.name << "  ";
		cout << "出生:" << p->data.brithday << "  " << endl;
		cout << p->data.name << "的子女:" << endl;
		if (p->lc == NULL)
		{
			cout << "无左孩子!";
		}
		else {
			cout << "辈分:" << p->lc->data.beifen << "  ";
			cout << "名字:" << p->lc->data.name << endl;
		}
		if (p->rc == NULL)
		{
			cout << "无右孩子!";
		}
		else {
			cout << "辈分:" << p->rc->data.beifen << "  ";
			cout << "名字:" << p->rc->data.name << endl;
		}


	}

}
void add_Function(TreeNode* t)//添加功能
{
	TreeNode* p, * q;
	char name[20];
	cout << "这位是谁的孩子:" << endl;
	cin >> name;
	q = findLocation(t, name);//查找当前名字返回的变量,为父亲节点
	if (q == NULL) 
	{ 
		cout << "双亲不存在" << endl; 
	}
	else {
		p = creatNode();//如果有这个父亲,就创建一个新的节点
		if (p) {
			p->data.beifen = q->data.beifen + 1; // 这是其父亲的辈分加 1
			p->lc = p->rc = NULL;
			if (q->lc == NULL) {
				q->lc = p;
				cout << "插入左子树成功!" << endl;
			}
			else {
				q = q->lc;
				//使用兄弟链表法
				while (q->rc != NULL) {
					q = q->rc;
				}
				q->rc = p;
				cout << "插入右子树成功!" << endl;

			}
		}
	}
}
void bianli(TreeNode* p, char father[])//写入祖宗
{
	ofstream w("D://in1.txt", ios::app);//追加
	if (!w) {
		cerr << "file could not be open." << endl;
		exit(0);
	}
	TreeNode* q;
	if (p)//左子树的不为空
	{
		w << father << "\t" << p->data.beifen << "\t" << p->data.name << "\t"
			<< p->data.brithday << "\t" << p->data.die << endl;
		bianli(p->lc, p->data.name); //遍历左子树 
		q = p->rc;
		while (q)   //遍历右子树          
		{
			w << father << "\t" << q->data.beifen << "\t" << q->data.name << "\t"
				<< q->data.brithday << "\t" << p->data.die << endl;
			bianli(q->lc, q->data.name);
			q = q->rc;
		}

	}
	w.close();
}
void save_File(TreeNode* p) //保存文件功能
{
	ofstream ofile;
	ofile.open("D://in1.txt", ios::out);//清空文件
	if (!ofile) {
		cerr << "file could not be open." << endl;
		exit(0);

	}
	if (p) {
		ofile << "\t" << p->data.beifen << "\t" << p->data.name << "\t"
			<< p->data.brithday << "\t" << p->data.die << "\t" << endl;
		if (p->lc) {
			bianli(p->lc, p->data.name);//兄弟链表,左子树开始遍历
		}
	}

	ofile.close();
}
void tree(char father[], char son[], int dai, int brithday, int die)//生成树
{
	TreeNode* t;
	TreeNode* p;
	p = findLocation(root, father);//爸爸
	if (p == NULL) { return; }
	t = findLocation(root, son);//儿子,找空的位置
	if (t != NULL) { return; }
	if (p->lc == NULL)//添加孩子
	{
		p->lc = new Node;
		p->lc->rc = p->lc->lc = NULL;
		cunru(p->lc, son, dai, brithday, die);
		cout << "插入左子树成功!" << endl;
	}
	else//添加前一个孩子的兄弟
	{
		p = p->lc;
		while (p->rc != NULL)
			p = p->rc;
		p->rc = new Node;
		p->rc->rc = p->rc->lc = NULL;
		cunru(p->rc, son, dai, brithday, die);
		cout << "插入右子树成功!" << endl;
	}
}
void read_File() {
	int dai, brithday, die;
	char son[10], father[10];
	root = new Node;//创建一个根节点
	root->lc = root->rc = NULL;
	ifstream read("D://in1.txt");//文件不存在会返回错误
	if (!read) {
		cerr << "file could not be open." << endl;
		exit(0);
	}
	read >> dai >> father >> brithday >> die;//读入祖宗
	cunru(root, father, dai, brithday, die);//存入结构体
	while (!read.eof())//如果不为空
	{
		read >> father >> dai >> son >> brithday >> die;//读取儿子
		tree(father, son, dai, brithday, die);//存入结构体
	}
	read.close();

}

void delete_Function(TreeNode*& p, char name[])//删除功能
{
	//地址指针
	if (p != NULL) {
		if (strcmp(p->data.name, name) == 0)
		{

			p = NULL;//当前节点值为空
			delete p;//删除当前节点
			cout << "删除成功!!!" << endl;
			return;
		}
		else 
		{ 
			cout << "查无此人" << endl; 
		}

		if (p->lc != NULL) { delete_Function(p->lc, name); }//找不到就遍历左边;
		if (p->rc != NULL) { delete_Function(p->rc, name); }//找不到就遍历右边;

	}

}
void look(TreeNode* p)   // 前序遍历
{

	if (p == NULL)return;
	else {
		putchar('(');
		cout << p->data.name;
		look(p->lc);
		look(p->rc);
		putchar(')');
	}
}
void printAll(TreeNode* p) {
	if (p != NULL) {
		cout << "辈分:" << p->data.beifen << "  ";
		cout << "姓名:" << p->data.name << "  ";

		cout << "出生:" << p->data.brithday << "  ";
		cout << "是否存活 0否1是:" << p->data.die << "  " << endl;
		if (p->lc != NULL) { printAll(p->lc); }//遍历孩子
		if (p->rc != NULL) { printAll(p->rc); }//遍历兄弟
	}
}

void menu() {
	cout << endl;
	cout << "--------------------------------------------------------" << endl;
	cout << ">>>                  1 --- 添加祖宗                  <<<" << endl;
	cout << ">>>                  2 --- 添加儿子                  <<<" << endl;
	cout << ">>>                  3 --- 删除名字                  <<<" << endl;
	cout << ">>>                  4 --- 查询一代人信息            <<<" << endl;
	cout << ">>>                  5 --- 查找名字                  <<<" << endl;
	cout << ">>>                  6 --- 括号法前序遍历            <<<" << endl;
	cout << ">>>                  7 --- 遍历全部信息              <<<" << endl;
	cout << ">>>                  9 --- 手动保存                  <<<" << endl;
	cout << ">>>                 10 --- 手动读取                  <<<" << endl;
	cout << ">>>                 11 --- 清屏                      <<<" << endl;
	cout << "--------------------------------------------------------" << endl;
}

int main()
{

	int m;
	char name[20];
	while (1) {
		menu();
		cout << ">>请输入选项>>:";
		cin >> m;
		switch (m) {
		case 1:
			if (root != NULL) { cout << "已经存在祖宗!" << endl; }
			else { root = creatFirst(); }   break;
		case 2:
			if (root == NULL) { cout << "请创建祖宗先" << endl; break; }
			add_Function(root); break;
		case 3:
			if (root == NULL) { cout << "请创建祖宗先" << endl; break; }
			cout << "输入删除的姓名" << endl; cin >> name; delete_Function(root, name); break;
		case 4:
			if (root == NULL) { cout << "请创建祖宗先" << endl; break; }
			char ch1;
			cout << "请输入这一代的字" << endl;
			cin >> ch1;
			searchByChar(root, ch1);
		case 5:
			if (root == NULL) { cout << "请创建祖宗先" << endl; break; }
			cout << "输入查找的姓名" << endl;
			cin >> name;
			find_Function(root, name); break;
		case 6:
			if (root == NULL) { cout << "请创建祖宗先" << endl; break; }
			look(root); break;
		case 7:
			if (root == NULL) { cout << "请创建祖宗先" << endl; break; }
			printAll(root); break;

		case 9:
			if (root == NULL) { cout << "请创建祖宗"; break; }
			save_File(root); cout << "保存成功!!!" << endl; break;
		case 10:
			read_File(); break;
		case 11:
			system("cls"); break;
		default:
			cout << "输入错误!!!" << endl; break;
		}
	}
	system("pause");
	return 0;
}

4. 运行截图

(1)读取

(2)插入:给某个人添加一个孩子

(3)删除:删除某个人,如果某人有后代,不允许删除

(4)堂兄弟:根据所在世代的字,可以输出该世代所有人的信息

(5)父子:可以根据姓名查询,并输出该人的父亲和孩子信息

(6)显示:以凹入表的形式显示家谱

(7)退出时,家谱信息保存到文件中

文章来源:https://blog.csdn.net/weixin_63524946/article/details/135410992
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。