【功能描述】
使用树形结构设计家族族谱数据管理系统。
【具体要求】
要求实现以下功能:
1. 使用树形结构设计家族族谱数据结构,定义节点(成员)的信息,
包括姓名、性别、出生日期、配偶、子女等。
2. 族谱构建:从用户输入的初始数据(如根节点信息)构建家族族谱
树,并允许逐步添加成员。
3. 添加成员:根据用户输入的信息添加新的家庭成员,并维护正确的
树结构。
4. 删除成员:根据用户输入的姓名删除指定成员,并确保树结构的完
整性。
5. 查找成员:根据用户输入的姓名查找并返回该成员的信息。
6. 遍历操作:实现家族族谱的前序遍历、中序遍历和后序遍历,并输
出遍历结果。
7. 用户界面:设计一个简单的命令行界面或图形界面,方便用户进行
各种操作,如添加、删除、查找成员,展示族谱等。
【可选部分】
1. 统计和分析:统计家族成员的数量、不同性别成员的数量、最长家
族树分支等。分析家族树的深度、平均每代成员数量等信息。
2. 关系查询:实现查询特定成员与其他成员的关系(如父子、祖孙、
兄弟姐妹等)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<windows.h>
// 家庭成员结构体
typedef struct family {
char name[40]; // 姓名
char gender[10]; // 性别
char birthday[20]; // 出生日期
char spouse[40]; // 配偶
struct family *children[5]; // 子女
int childCount; // 子女数量
struct family *parent; // 父母
} family;
family* root = NULL; // 根节点
int maleCount,femaleCount;// 家族中男,女成员数量
char ch;
// 创建新成员
family* create(char* name, char* gender, char* birthday,char* spouse) {
family* newfamily = (family*)malloc(sizeof(family)); // 分配内存
strcpy(newfamily->name, name); // 设置姓名
strcpy(newfamily->gender, gender); // 设置性别
strcpy(newfamily->birthday, birthday); // 设置出生日期
strcpy(newfamily->spouse, spouse); //设置配偶
newfamily->childCount = 0; // 初始化子女数量为0
newfamily->parent = NULL; // 初始化父母为空
return newfamily; // 返回新成员
}
// 添加子女
void addChild(family* parent, family* child) {
if (parent->childCount < 5) { // 如果子女数量少于5
parent->children[parent->childCount++] = child; // 添加子女
child->parent = parent; // 设置父母
} else {
printf("无法添加更多的子女。\n");
}
}
// 初始化家族树
void initialFamilyTree() {
char name[40], gender[10], birthday[20],spouse[40];
printf("请输入根成员的姓名 性别 出生日期 配偶: "); // 提示输入根成员姓名 性别 出生日期 配偶
scanf("%s %s %s %s", name,gender,birthday, spouse );
root = create(name, gender, birthday,spouse); // 创建根成员
}
// 查找成员
family* findMember(family* root, char* name) {
if (root == NULL) {
return NULL;
}
if (strcmp(root->name, name) == 0) { // 如果找到成员
return root;
}
for (int i = 0; i < root->childCount; i++) { // 遍历子女
family* found = findMember(root->children[i], name); // 递归查找
if (found != NULL) { // 如果找到成员
return found;
}
}
return NULL; // 未找到成员
}
// 添加家庭成员
void addFamily() {
if (root == NULL) { // 如果根节点为空
printf("家族树未初始化。\n"); // 提示家族树未初始化
return;
}
char parentName[40];
printf("请输入父母的姓名: "); // 提示输入父母姓名
scanf("%s", parentName);
family* parent = findMember(root, parentName); // 查找父母
if (parent == NULL) { // 如果未找到父母
printf("未找到父母。\n"); // 提示未找到父母
return;
}
char name[40], gender[10], birthday[20],spouse[40];
printf("请输入孩子的姓名 性别 出生日期 配偶: "); // 提示输入孩子姓名 性别 出生日期 配偶
scanf("%s %s %s %s", name,gender,birthday, spouse );
family* child = create(name, gender, birthday,spouse); // 创建孩子
addChild(parent, child); // 添加孩子到父母节点
}
// 删除家庭成员
void deleteFamily() {
if (root == NULL) { // 如果根节点为空
printf("家族树未初始化。\n"); // 提示家族树未初始化
return;
}
char name[40];
printf("请输入要删除的成员姓名: "); // 提示输入要删除的成员姓名
scanf("%s", name);
if (strcmp(root->name, name) == 0) { // 如果要删除的是根节点
printf("无法删除根成员。\n"); // 提示无法删除根成员
return;
}
family* member = findMember(root, name); // 查找要删除的成员
if (member == NULL) { // 如果未找到成员
printf("未找到成员。\n"); // 提示未找到成员
return;
}
family* parent = member->parent; // 获取成员的父母
for (int i = 0; i < parent->childCount; i++) { // 遍历父母的子女
if (parent->children[i] == member) { // 找到要删除的成员
for (int j = i; j < parent->childCount - 1; j++) {
parent->children[j] = parent->children[j + 1]; // 移动子女位置
}
parent->childCount--; // 减少子女数量
free(member); // 释放成员内存
printf("成员删除成功。\n"); // 提示成员删除成功
return;
}
}
}
// 查找家庭成员
void findFamily() {
if (root == NULL) {
printf("家族树未初始化。\n");
return;
}
char name[50];
printf("请输入要查找的成员姓名: ");
scanf("%s", name);
family* member = findMember(root, name); // 查找成员
if (member == NULL) { // 如果未找到成员
printf("未找到成员。\n"); // 提示未找到成员
} else {
printf("姓名: %s\n", member->name); // 输出成员姓名
printf("性别: %s\n", member->gender); // 输出成员性别
printf("出生日期: %s\n", member->birthday); // 输出成员出生日期
printf("配偶: %s\n", member->spouse); // 输出配偶姓名
if (member->childCount > 0) { // 如果有子女
printf("子女: ");
for (int i = 0; i < member->childCount; i++) {
printf("%s ", member->children[i]->name); // 输出子女姓名
}
printf("\n");
}
}
}
// 前序遍历
void preOrderTraversal(family* root) {
if (root == NULL) return;
printf("%s ", root->name);
for (int i = 0; i < root->childCount; i++)
preOrderTraversal(root->children[i]); // 递归前序遍历子女
}
// 中序遍历
void inOrderTraversal(family* root) {
if (root == NULL) return;
if (root->childCount > 0)
inOrderTraversal(root->children[0]); // 递归中序遍历第一个子女
printf("%s ", root->name);
for (int i = 1; i < root->childCount; i++)
inOrderTraversal(root->children[i]); // 递归中序遍历其他子女
}
// 后序遍历
void postOrderTraversal(family* root) {
if (root == NULL) return;
for (int i = 0; i < root->childCount; i++)
postOrderTraversal(root->children[i]); // 递归后序遍历子女
printf("%s ", root->name);
}
// 打印遍历结果
void printTraversals() {
if (root == NULL) {
printf("家族树未初始化。\n");
return;
}
printf("前序遍历: ");
preOrderTraversal(root); // 前序遍历
printf("\n");
printf("中序遍历: ");
inOrderTraversal(root); // 中序遍历
printf("\n");
printf("后序遍历: ");
postOrderTraversal(root); // 后序遍历
printf("\n");
}
//家族成员的数量
int countFamilyMembers(struct family *root) {
if (root == NULL) {
return 0;
}
int count = 1; // 当前节点算一个成员
for (int i = 0; i < root->childCount; i++) {
count += countFamilyMembers(root->children[i]); // 递归统计子节点的成员数量
}
return count;
}
// 家族中男,女成员数量
void countGender(struct family *root) {
if (root == NULL) {
return;
}
if (strcmp(root->gender, "男") == 0) {
maleCount++;
} else if (strcmp(root->gender, "女") == 0) {
femaleCount++;
}
for (int i = 0; i < root->childCount; i++) {
countGender(root->children[i]); // 递归统计子节点的性别数量
}
}
//家族树的深度
int calculateDepth(struct family *root) {
if (root == NULL) {
return 0;
}
int maxDepth = 0;
for (int i = 0; i < root->childCount; i++) {
int childDepth = calculateDepth(root->children[i]);
if (childDepth > maxDepth) {
maxDepth = childDepth;
}
}
return 1 + maxDepth;
}
//关系查询
int isParent(family* parent, family* child) {
if (parent == NULL || child == NULL) return 0;
for (int i = 0; i < parent->childCount; ++i) {
if (parent->children[i] == child) return 1;
}
return 0;
}
int isChild(family* parent, family* child) {
return isParent(child, parent); // 调用isParent,但方向相反
}
int isGrandparent(family* gp, family* grandchild) {
if (gp == NULL || grandchild == NULL) return 0;
for (int i = 0; i < gp->childCount; ++i) {
family* child = gp->children[i];
for (int j = 0; j < child->childCount; ++j) {
if (child->children[j] == grandchild) return 1;
}
}
return 0;
}
int isGrandchild(family* gp, family* grandchild){
return isGrandparent(grandchild, gp); // 调用isGrandparent,但方向相反
}
void print(){
char name1[50],name2[50];
printf("请输入要查找的成员姓名: ");
scanf("%s %s", name1, name2);
family* alice = findMember(root, name1);
family* bob = findMember(root, name2);
if(alice==NULL||bob==NULL) {
if(alice==NULL) printf("未找到成员: %s\n",name1);
if(bob==NULL) printf("未找到成员: %s\n",name2);
return ;
} else {
if (isParent(alice, bob)) {
if(strcmp(alice->gender, "男") == 0) printf("%s 是 %s 的 父亲\n",name1,name2);
else printf("%s 是 %s 的 母亲\n",name1,name2);
} else if (isChild(alice, bob)) {
if(strcmp(alice->gender, "男") == 0) printf("%s 是 %s 的 儿子\n",name1,name2);
else printf("%s 是 %s 的 女儿\n",name1,name2);
} else if (isGrandparent(alice, bob)) {
if(strcmp(alice->gender, "男") == 0) printf("%s 是 %s 的 祖父\n",name1,name2);
else printf("%s 是 %s 的 祖母\n",name1,name2);
} else if(isGrandchild(alice, bob)){
if(strcmp(alice->gender, "男") == 0) printf("%s 是 %s 的 孙子\n",name1,name2);
else printf("%s 是 %s 的 孙女\n",name1,name2);
}else {
printf(" %s 和 %s 找不到直接关系\n", alice->name, bob->name);
}
}
}
// 显示菜单
void display() {
printf("家族树管理系统\n");
printf("1. 初始化家族树\n");
printf("2. 添加家庭成员\n");
printf("3. 删除家庭成员\n");
printf("4. 查找家庭成员\n");
printf("5. 打印遍历结果\n");
printf("6. 统计与分析\n");
printf("7. 关系查询\n");
printf("8. 退出\n");
printf("请输入你的选择: ");
}
// 主函数
int main() {
int n;
int k,t;
do {
display(); // 显示菜单
scanf("%d", &n);
switch (n) {
case 1:
initialFamilyTree(); // 初始化家族树
printf("初始化成功,三秒后返回...");
Sleep(3000);
system("cls");
break;
case 2:
addFamily(); // 添加家庭成员
printf("添加成功,三秒后返回...");
Sleep(3000);
system("cls");
break;
case 3:
deleteFamily(); // 删除家庭成员
printf("删除成功,三秒后返回...");
Sleep(3000);
system("cls");
break;
case 4:
findFamily(); // 查找家庭成员
printf("按任意键返回:");
getchar();
scanf("%c",&ch);
system("cls");
break;
case 5:
printTraversals(); // 打印遍历结果
printf("按任意键返回:");
getchar();
scanf("%c",&ch);
system("cls");
break;
case 6:
k=countFamilyMembers(root);//家族成员的数量
t=calculateDepth(root);//家族树的深度
countGender(root);//家族中男,女成员数量
printf("家族成员的数量: %d\n",k);
printf("男成员的数量: %d\n 女成员的数量: %d\n",maleCount,femaleCount);
printf("家族树的深度: %d\n",t);
printf("平均每代成员数量: %lf\n",(double)k/(double)t);
maleCount=0,femaleCount=0;
printf("按任意键返回:");
getchar();
scanf("%c",&ch);
system("cls");
break;
case 7:
print(); //关系查询
printf("按任意键返回:");
getchar();
scanf("%c",&ch);
system("cls");
break;
case 8:
exit(0);
default:
printf("无效的选择。请重试。\n"); // 提示无效选择
}
} while (n != 8); // 如果选择不是7,继续循环
return 0;
}
小结
这个代码我用的是多叉树,也可以用儿子-兄弟法来写。整体来说,这个代码还有许多可以改进的地方。毕竟我在测试的时候就觉得很别扭,当然因为本人比较懒,所以在满足课程要求的情况下没改。希望东软的学弟学妹可以看到这代码。