用二叉树表示家谱关系,并实现各种查找功能
用二叉树表示家谱关系,并实现各种查找功能(扩展)
目的: 掌握二叉树遍历算法的应用,熟练使用先序、中序、后序三种递归遍历算法进行二叉树问题的求解。
内容: 用C语言编写程序,采用一棵二叉树,表示一个家谱关系(由若干家谱记录构成,每个家谱记录由父亲妻子和儿子的姓名构成,其中姓名是关键字),要求程序具有以下功能。
① 文件操作功能:家谱记录的输入,家谱记录的输出,清除全部文件记录和将家谱记录存盘。要求在输入家谱记录时按从祖先到子孙的顺序输入,第一个家谱记录的父亲域为所有人的祖先。
② 家谱操作功能:用括号表示法输出家谱二叉树,查找某人的所有儿子,查找某人的所有祖先(这里的祖先是指所设计的二叉树结构中某结点的所有祖先结点)。
分析:
要实现这个功能,首先需要定义一个家谱记录的结构体,包含父亲、妻子和儿子的姓名等信息。然后定义一个二叉树节点结构体,包含家谱记录和左右子节点的指针。接着,需要实现二叉树的创建、遍历、查找、输出等操作。
具体实现:
- 家谱记录结构体定义
typedef struct {
char father[20];
char wife[20];
char son[20];
} GenealogyRecord;
- 二叉树节点结构体定义
typedef struct TreeNode {
GenealogyRecord record;
struct TreeNode* left;
struct TreeNode* right;
} TreeNode;
- 二叉树的创建
TreeNode* createTree(GenealogyRecord* records, int n) {
// 创建根节点
TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
root->record = records[0];
root->left = NULL;
root->right = NULL;
// 逐个插入节点
for (int i = 1; i < n; i++) {
TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
node->record = records[i];
node->left = NULL;
node->right = NULL;
TreeNode* p = root;
while (1) {
if (strcmp(node->record.father, p->record.son) == 0) {
if (p->left == NULL) {
p->left = node;
break;
} else {
p = p->left;
}
} else if (strcmp(node->record.father, p->record.wife) == 0) {
if (p->right == NULL) {
p->right = node;
break;
} else {
p = p->right;
}
} else {
printf("Invalid record!\n");
break;
}
}
}
return root;
}
- 二叉树的遍历
void preOrder(TreeNode* root) {
if (root == NULL) {
return;
}
printf("%s ", root->record.son);
preOrder(root->left);
preOrder(root->right);
}
void inOrder(TreeNode* root) {
if (root == NULL) {
return;
}
inOrder(root->left);
printf("%s ", root->record.son);
inOrder(root->right);
}
void postOrder(TreeNode* root) {
if (root == NULL) {
return;
}
postOrder(root->left);
postOrder(root->right);
printf("%s ", root->record.son);
}
- 查找某人的所有儿子
void findSons(TreeNode* root, char* name) {
if (root == NULL) {
return;
}
if (strcmp(root->record.father, name) == 0) {
printf("%s ", root->record.son);
}
findSons(root->left, name);
findSons(root->right, name);
}
- 查找某人的所有祖先
void findAncestors(TreeNode* root, char* name) {
if (root == NULL) {
return;
}
if (strcmp(root->record.son, name) == 0) {
return;
}
if (strcmp(root->record.wife, name) == 0) {
printf("%s ", root->record.father);
findAncestors(root->left, root->record.father);
findAncestors(root->right, root->record.father);
} else {
findAncestors(root->left, name);
findAncestors(root->right, name);
}
}
- 用括号表示法输出家谱二叉树
void printTree(TreeNode* root) {
if (root == NULL) {
return;
}
printf("%s", root->record.son);
if (root->left != NULL || root->right != NULL) {
printf("(");
printTree(root->left);
if (root->right != NULL) {
printf(",");
printTree(root->right);
}
printf(")");
}
}
完整代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 家谱记录结构体定义
typedef struct {
char father[20];
char wife[20];
char son[20];
} GenealogyRecord;
// 二叉树节点结构体定义
typedef struct TreeNode {
GenealogyRecord record;
struct TreeNode* left;
struct TreeNode* right;
} TreeNode;
// 创建二叉树
TreeNode* createTree(GenealogyRecord* records, int n) {
// 创建根节点
TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
root->record = records[0];
root->left = NULL;
root->right = NULL;
// 逐个插入节点
for (int i = 1; i < n; i++) {
TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
node->record = records[i];
node->left = NULL;
node->right = NULL;
TreeNode* p = root;
while (1) {
if (strcmp(node->record.father, p->record.son) == 0) {
if (p->left == NULL) {
p->left = node;
break;
} else {
p = p->left;
}
} else if (strcmp(node->record.father, p->record.wife) == 0) {
if (p->right == NULL) {
p->right = node;
break;
} else {
p = p->right;
}
} else {
printf("Invalid record!\n");
break;
}
}
}
return root;
}
// 先序遍历
void preOrder(TreeNode* root) {
if (root == NULL) {
return;
}
printf("%s ", root->record.son);
preOrder(root->left);
preOrder(root->right);
}
// 中序遍历
void inOrder(TreeNode* root) {
if (root == NULL) {
return;
}
inOrder(root->left);
printf("%s ", root->record.son);
inOrder(root->right);
}
// 后序遍历
void postOrder(TreeNode* root) {
if (root == NULL) {
return;
}
postOrder(root->left);
postOrder(root->right);
printf("%s ", root->record.son);
}
// 查找某人的所有儿子
void findSons(TreeNode* root, char* name) {
if (root == NULL) {
return;
}
if (strcmp(root->record.father, name) == 0) {
printf("%s ", root->record.son);
}
findSons(root->left, name);
findSons(root->right, name);
}
// 查找某人的所有祖先
void findAncestors(TreeNode* root, char* name) {
if (root == NULL) {
return;
}
if (strcmp(root->record.son, name) == 0) {
return;
}
if (strcmp(root->record.wife, name) == 0) {
printf("%s ", root->record.father);
findAncestors(root->left, root->record.father);
findAncestors(root->right, root->record.father);
} else {
findAncestors(root->left, name);
findAncestors(root->right, name);
}
}
// 用括号表示法输出家谱二叉树
void printTree(TreeNode* root) {
if (root == NULL) {
return;
}
printf("%s", root->record.son);
if (root->left != NULL || root->right != NULL) {
printf("(");
printTree(root->left);
if (root->right != NULL) {
printf(",");
printTree(root->right);
}
printf(")");
}
}
int main() {
// 家谱记录
GenealogyRecord records[] = {
{"A", "B", "C"},
{"C", "D", "E"},
{"C", "D", "F"},
{"E", "G", "H"},
{"F", "I", "J"},
{"H", "K", "L"}
};
int n = sizeof(records) / sizeof(records[0]);
// 创建二叉树
TreeNode* root = createTree(records, n);
// 测试输出
printf("先序遍历:");
preOrder(root);
printf("\n");
printf("中序遍历:");
inOrder(root);
printf("\n");
printf("后序遍历:");
postOrder(root);
printf("\n");
printf("用括号表示法输出家谱二叉树:");
printTree(root);
printf("\n");
printf("查找C的所有儿子:");
findSons(root, "C");
printf("\n");
printf("查找L的所有祖先:");
findAncestors(root, "L");
printf("\n");
return 0;
}
原文地址: https://www.cveoy.top/t/topic/opTF 著作权归作者所有。请勿转载和采集!