采用树表示一个家谱关系,采用链表作为存储结构,实现家谱关系的相关运算,每个节点信息包含有:姓名 性别 配偶姓名 年龄 出生日期
时间: 2024-03-30 17:40:02 浏览: 124
好的,这是一个家谱关系的问题,需要用树结构进行表示,并且采用链表作为存储结构。每个节点信息包括姓名、性别、配偶姓名、年龄以及出生日期。实现家谱关系的相关运算可以包括以下几个方面:
1. 添加家庭成员:可以通过向树中添加节点的方式来添加家庭成员,每个节点代表一个家庭成员。插入操作可以采用递归的方式实现。
2. 删除家庭成员:可以通过删除树中的节点来删除家庭成员。删除操作也可以采用递归的方式实现。
3. 查找家庭成员:可以通过遍历树来查找家庭成员。可以按照姓名、性别、年龄等信息进行查找。
4. 修改家庭成员信息:可以通过遍历树来找到需要修改的节点,然后对节点的信息进行修改。
5. 查询家庭成员关系:可以通过遍历树来查询家庭成员之间的关系。比如查询某个人的父母、配偶、兄弟姐妹等。
6. 显示家谱树:可以通过遍历树来将家谱树以一定的格式输出。
以上就是家谱关系的相关运算,可以通过树结构和链表存储结构来实现。
相关问题
用c语言写:采用树表示一个家谱关系 采用链表(孩子表示法)作为存储结构,实现家谱关系的相关运算。每个节点信息包含有:姓名、性别、配偶姓名、身份证号、年龄、出生日期等。 功能要求: 1)输入家族信息(要求自己设计文件存储格式,存放当前所有家族信息)2)输出家族信息(要求界面输出格式直观明了) 3)查找某人的所有儿子 4)查找某人的双亲
以下是一个简单的实现,包含了基本的功能要求。
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 家谱节点信息
typedef struct _familyTreeNode {
char name[20]; // 姓名
char sex[6]; // 性别
char spouseName[20]; // 配偶姓名
char id[20]; // 身份证号
int age; // 年龄
char birthDate[20]; // 出生日期
struct _familyTreeNode *parent; // 父节点
struct _familyTreeNode *children; // 子节点链表
} FamilyTreeNode;
// 创建家谱节点
FamilyTreeNode *createFamilyTreeNode(char *name, char *sex, char *spouseName, char *id, int age, char *birthDate) {
FamilyTreeNode *node = (FamilyTreeNode*) malloc(sizeof(FamilyTreeNode));
strcpy(node->name, name);
strcpy(node->sex, sex);
strcpy(node->spouseName, spouseName);
strcpy(node->id, id);
node->age = age;
strcpy(node->birthDate, birthDate);
node->parent = NULL;
node->children = NULL;
return node;
}
// 添加子节点
void addChild(FamilyTreeNode *parent, FamilyTreeNode *child) {
child->parent = parent;
child->children = parent->children;
parent->children = child;
}
// 根据姓名查找节点
FamilyTreeNode *findNodeByName(FamilyTreeNode *root, char *name) {
if (strcmp(root->name, name) == 0) {
return root;
} else {
FamilyTreeNode *p = root->children;
while (p != NULL) {
FamilyTreeNode *q = findNodeByName(p, name);
if (q != NULL) {
return q;
}
p = p->children;
}
return NULL;
}
}
// 查找某人的所有儿子
void findSons(FamilyTreeNode *node) {
FamilyTreeNode *p = node->children;
while (p != NULL) {
if (strcmp(p->sex, "男") == 0) {
printf("%s\n", p->name);
}
p = p->children;
}
}
// 查找某人的双亲
void findParents(FamilyTreeNode *node) {
if (node->parent != NULL) {
printf("父亲:%s\n", node->parent->name);
}
if (strcmp(node->sex, "女") == 0 && strlen(node->spouseName) > 0) {
FamilyTreeNode *spouse = findNodeByName(node, node->spouseName);
if (spouse != NULL) {
printf("丈夫:%s\n", spouse->name);
}
}
}
int main() {
// 初始化家谱
FamilyTreeNode *root = createFamilyTreeNode("张三", "男", "", "000000000000000000", 60, "1960-01-01");
FamilyTreeNode *node1 = createFamilyTreeNode("李四", "男", "王五", "111111111111111111", 35, "1985-01-01");
FamilyTreeNode *node2 = createFamilyTreeNode("王五", "女", "李四", "222222222222222222", 32, "1988-01-01");
FamilyTreeNode *node3 = createFamilyTreeNode("赵六", "女", "", "333333333333333333", 28, "1992-01-01");
addChild(root, node1);
addChild(node1, node2);
addChild(node1, node3);
// 输出家族信息
printf("家族信息:\n");
printf("姓名\t性别\t配偶姓名\t身份证号\t\t年龄\t出生日期\n");
printf("----------------------------------------------------------\n");
printf("%s\t%s\t%s\t\t%s\t%d\t%s\n", root->name, root->sex, root->spouseName, root->id, root->age, root->birthDate);
FamilyTreeNode *p = root->children;
while (p != NULL) {
printf("%s\t%s\t%s\t\t%s\t%d\t%s\n", p->name, p->sex, p->spouseName, p->id, p->age, p->birthDate);
p = p->children;
}
// 查找某人的所有儿子
printf("\n请输入要查找儿子的人的姓名:");
char name[20];
scanf("%s", name);
FamilyTreeNode *node = findNodeByName(root, name);
if (node == NULL) {
printf("未找到该人!\n");
} else {
printf("所有儿子:\n");
findSons(node);
}
// 查找某人的双亲
printf("\n请输入要查找双亲的人的姓名:");
scanf("%s", name);
node = findNodeByName(root, name);
if (node == NULL) {
printf("未找到该人!\n");
} else {
printf("双亲:\n");
findParents(node);
}
return 0;
}
```
注意,这只是一个简单的实现,有很多方面可以进行优化和改进。例如,可以添加更多的家谱节点信息,支持更多的操作,增加错误处理等。
采用树表示一个家谱关系,采用链表(孩子表示法)作为存储结构,实现家谱关系的相关运算。每个节点信息包含有:姓名、性别、配偶姓名、身份证号、年龄、出生日期等。 功能要求: 1)输入家族信息(要求自己设计文件存储格式,存放当前所有家族信息)2)输出家族信息(要求界面输出格式直观明了) 3)查找某人的所有儿子 4)查找某人的双亲选做功能: 1)查找某人的所有祖先 2)查找某人的所有兄弟界面
很好,这是一个家谱关系的小项目,需要用到树和链表数据结构,下面我将分步骤进行讲解。
1. 设计文件存储格式
我们可以使用文本文件作为存储格式,每个节点信息之间用逗号或制表符隔开,每个节点占一行。例如:
```txt
姓名,性别,配偶姓名,身份证号,年龄,出生日期
张三,男,李四,123456789,30,1990-01-01
李四,女,张三,987654321,28,1992-05-15
王五,男,,111111111,60,1960-08-20
```
其中,配偶姓名为空表示此人未婚。
2. 定义节点结构体
我们定义一个节点结构体,包含姓名、性别、配偶姓名、身份证号、年龄、出生日期等信息。同时,为了实现孩子表示法,我们需要定义一个指向孩子节点的指针和一个指向兄弟节点的指针。
```c++
struct Node {
string name;
string gender;
string spouseName;
string idNumber;
int age;
string birthDate;
Node* child;
Node* sibling;
};
```
3. 实现读取文件并构建家谱树
我们可以定义一个函数,读取存储家族信息的文本文件,并构建家谱树。读取文本文件可以使用 ifstream 类,构建家谱树可以使用递归方法。
```c++
Node* buildTreeFromFile(string fileName) {
ifstream fin(fileName);
if (!fin.is_open()) {
cout << "Failed to open file: " << fileName << endl;
return nullptr;
}
string line;
getline(fin, line); // 读取第一行,抛弃
Node* root = nullptr;
unordered_map<string, Node*> nodeMap; // 用哈希表存储已经创建的节点
while (getline(fin, line)) {
stringstream ss(line);
string name, gender, spouseName, idNumber, birthDate;
int age;
getline(ss, name, ',');
getline(ss, gender, ',');
getline(ss, spouseName, ',');
getline(ss, idNumber, ',');
ss >> age;
getline(ss, birthDate);
Node* node = new Node{name, gender, spouseName, idNumber, age, birthDate, nullptr, nullptr};
nodeMap[idNumber] = node; // 将节点存入哈希表
if (!root) {
root = node; // 如果根节点还没有创建,将第一个节点作为根节点
} else {
// 将节点插入到家谱树中
if (!spouseName.empty()) {
// 如果有配偶,将配偶插入到家谱树中
if (nodeMap.count(spouseName)) {
Node* spouse = nodeMap[spouseName];
node->sibling = spouse->child;
spouse->child = node;
} else {
Node* spouse = new Node{spouseName, gender == "男" ? "女" : "男", name, "", age, birthDate, nullptr, nullptr};
nodeMap[spouseName] = spouse;
node->sibling = spouse->child;
spouse->child = node;
}
} else {
// 如果没有配偶,将节点插入到兄弟节点中
Node* parent = nodeMap[idNumber.substr(0, 16) + "00000000"]; // 获得父亲节点
node->sibling = parent->child;
parent->child = node;
}
}
}
fin.close();
return root;
}
```
4. 实现输出家族信息
我们可以定义一个函数,遍历家谱树,并输出每个节点的信息。这里我们采用前序遍历算法。
```c++
void printFamilyTree(Node* root) {
if (!root) {
return;
}
cout << root->name << " " << root->gender << " 身份证号:" << root->idNumber << " 年龄:" << root->age << " 出生日期:" << root->birthDate << endl;
Node* child = root->child;
while (child) {
printFamilyTree(child);
child = child->sibling;
}
}
```
5. 实现查找某人的所有儿子
我们可以定义一个函数,输入某人的身份证号,查找该人的所有儿子。遍历该人的孩子链表,并筛选出所有性别为男的孩子。
```c++
vector<Node*> findSons(Node* root, string idNumber) {
vector<Node*> sons;
Node* node = findNode(root, idNumber);
if (node) {
Node* child = node->child;
while (child) {
if (child->gender == "男") {
sons.push_back(child);
}
child = child->sibling;
}
}
return sons;
}
```
其中,findNode 函数可以用递归的方法实现,查找身份证号为 idNumber 的节点。
6. 实现查找某人的双亲
我们可以定义一个函数,输入某人的身份证号,查找该人的双亲。由于一个节点可能有多个父亲(比如再婚的情况),我们可以将所有父亲节点放入一个 vector 中返回。
```c++
vector<Node*> findParents(Node* root, string idNumber) {
vector<Node*> parents;
Node* node = findNode(root, idNumber);
if (node) {
string fatherId = idNumber.substr(0, 16) + "00000000";
if (findNode(root, fatherId)) {
parents.push_back(findNode(root, fatherId));
}
string motherId = idNumber.substr(0, 16) + "11111111";
if (findNode(root, motherId)) {
parents.push_back(findNode(root, motherId));
}
}
return parents;
}
```
7. 实现查找某人的所有祖先
我们可以定义一个函数,输入某人的身份证号,查找该人的所有祖先。由于一个节点可能有多个父亲,我们可以递归查找所有父亲的父亲,直到根节点。
```c++
vector<Node*> findAncestors(Node* root, string idNumber) {
vector<Node*> ancestors;
Node* node = findNode(root, idNumber);
vector<Node*> parents = findParents(root, idNumber);
for (Node* parent : parents) {
ancestors.push_back(parent);
vector<Node*> grandParents = findAncestors(root, parent->idNumber);
ancestors.insert(ancestors.end(), grandParents.begin(), grandParents.end());
}
return ancestors;
}
```
8. 实现查找某人的所有兄弟
我们可以定义一个函数,输入某人的身份证号,查找该人的所有兄弟。由于一个节点可能有多个兄弟,我们可以遍历该节点的兄弟链表,并筛选出所有不是该节点本人的兄弟。
```c++
vector<Node*> findSiblings(Node* root, string idNumber) {
vector<Node*> siblings;
Node* node = findNode(root, idNumber);
if (node) {
Node* parent = findNode(root, idNumber.substr(0, 16) + "00000000"); // 获得父亲节点
Node* child = parent->child;
while (child) {
if (child != node) {
siblings.push_back(child);
}
child = child->sibling;
}
}
return siblings;
}
```
到这里,我们已经完成了家谱关系的相关运算,下面是完整的代码:
阅读全文