族谱管理

族谱(或称家谱)是一种以表谱形式,记载一个以血缘关系为主体的家族世系繁衍和重要人物事迹的特殊图书体裁。族谱是中国特有的文化遗产,是中华民族的三大文献(国史,地志,族谱)之一,属珍贵的人文资料,对于历史学、民俗学、人口学、社会学和经济学的深入研究,均有其不可替代的独特功能。本题对族谱管理进行简单的模拟,以实现查看祖先和子孙个人信息、插入家族成员、删除家族成员、修改家族成员信息、按事迹查找家族成员、列出全部家族成员及关系等功能。家族成员至少包括姓名、性别、生卒年月、配偶、简介等信息,数据结构可自行设计。

#include <stdio.h>
#include <malloc.h>
#include<string.h>
#define maxsize 100
typedef struct
{
    char name[maxsize];         //姓名
    char sex[maxsize];          //性别
    char bir[maxsize];          //出生日期
    char mate[maxsize];         //配偶
    char info[maxsize];         //简介
    int generation;             //第几代
}ElemType;
typedef struct node
{
    ElemType data;
    struct node *brother;       //左孩子
    struct node *child;         //右孩子
} BTNode;

void print(BTNode *&p)//输出节点内容
{
    printf("姓名:%s\n",p->data.name);
    printf("性别:%s\n",p->data.sex);
    printf("出生日期:%s\n",p->data.bir);
    printf("配偶:%s\n",p->data.mate);
    printf("简介:%s\n",p->data.info);
}
BTNode *create()//创建一个节点
{
    BTNode *p;
    p = (BTNode *)malloc(sizeof(BTNode));
    printf("请输入姓名:\n");
    scanf("%s",p->data.name);
    printf("请输入性别:\n");
    scanf("%s",p->data.sex);
    printf("请输入出生年月日:\n");
    scanf("%s",p->data.bir);
    printf("请输入配偶的姓名:\n");
    scanf("%s",p->data.mate);
    printf("请输入简介:\n");
    scanf("%s",p->data.info);
    printf("信息写入成功!\n");
    p->child = NULL;
    p->brother = NULL;
    return p;
}

BTNode *createFirst()//创建祖先
{
    BTNode *head;
    head = (BTNode *)malloc(sizeof(BTNode));
    printf("请输入祖先姓名:\n");
    scanf("%s",head->data.name);
    printf("请输入祖先性别:\n");
    scanf("%s",head->data.sex);
    printf("请输入祖先出生年月日:\n");
    scanf("%s",head->data.bir);
    printf("请输入祖先的配偶的姓名:\n");
    scanf("%s",head->data.mate);
    printf("请输入对祖先的简介:\n");
    scanf("%s",head->data.info);
    head ->data.generation = 1;
    head->brother = NULL;
    head->child = NULL;
    printf("祖先写入成功!\n");
    return head;
}

BTNode *preOrder(BTNode *&b,char name_[])//遍历查找
{
    BTNode *q;
    if(b == NULL)
        return NULL;
    if(strcmp(b->data.name,name_) == 0)
        return b;
    if(b->brother)
    {
        q=preOrder(b->brother,name_);  //在兄弟中找
        if(q)
            return q;
    }
    if(b->child)
    {
        q=preOrder(b->child,name_);   //在孩子中找
        if(q)
            return q;
    }
    return NULL;
}

void lookBrother(BTNode *&h)
{
    if(h != NULL)
    {
        printf("%s ",h->data.name);
        lookBrother(h->brother);
    }
}

void printAll(BTNode *&h)
{
    if(strcmp(h->data.name," ") != 0)
    {
        printf("第%d代的%s的孩子有:\n", h->data.generation, h->data.name);
        lookBrother(h->child);
        printf("\n");
    }
    if(h->child)
        printAll(h->child);
    if(h->brother)
        printAll(h->brother);
}

int addChild(BTNode *&head)
{
    char name[20];
    printf("请输入该孩子的父节点名称:\n");
    scanf("%s", name);
    BTNode *p,*q;
    p = create();
    q = preOrder(head,name);
    if(q->child == NULL)
    {
        p->data.generation = q->data.generation + 1;
        q->child = p;
        return 1;
    }
    else
    {
        q = q->child;
        while(q->brother != NULL)
        {
            q = q->brother;
        }
        p->data.generation = q->data.generation;
        q->brother = p;
        return 1;
    }
}

void printName(BTNode *&head)   //按姓名查询
{
    BTNode *node;
    char name[20];
    printf("请输入要查询的姓名:");
    scanf("%s", name);
    node = preOrder(head, name);
    print(node);
}

void deleteName(BTNode *&head)  //按姓名查询
{
    BTNode *node;
    char name[20];
    printf("请输入要删除的姓名:");
    scanf("%s", name);
    node = preOrder(head, name);
    node->child = NULL;
    strcpy(node->data.name," ");
    printf("已删除!\n");
}

void alterName(BTNode *&head)//按姓名修改
{
    BTNode *node, *newNode;
    char name[20];
    printf("请输入要修改的姓名:");
    scanf("%s", name);
    node = preOrder(head, name);
    newNode = create();
    strcpy(node->data.name, newNode->data.name);
    strcpy(node->data.bir, newNode->data.bir);
    strcpy(node->data.mate, newNode->data.mate);
    strcpy(node->data.info, newNode->data.info);
    strcpy(node->data.sex, newNode->data.sex);
}

void GetNextval(char line[], int nextval[])//对模式串求next[]值
{
    int j=0,k=-1;
    nextval[0]=-1;
    while(j<strlen(line))
    {
        if(k==-1 || line[j]==line[k])//k为-1或字符相等时
        {
            j++;
            k++;
            if(line[j]!=line[k])
                nextval[j]=k;
            else
                nextval[j]=nextval[k];
        }
        else k=nextval[k];
    }
}

int KMP(char s[], char line[])//kmp算法实现
{
    int sl=strlen(s);
    int ll=strlen(line);
    int nextval[maxsize],i=0,j=0;
    GetNextval(line,nextval);
    while(i< sl&& j<ll)
    {
        if(j==-1 || s[i]==line[j])
        {
            i++;
            j++;
        }
        else
        {
            j=nextval[j];
        }
        sl=strlen(s);
        ll=strlen(line);
    }
    if(j>=strlen(line))
        return (i-strlen(line));//返回匹配模式串的首字符下标
    else
		return -1;//返回不匹配标志
}

BTNode *keySearch(BTNode *&b,char name[])//关键字查找
{
    BTNode *q;

    if(b == NULL)
        return NULL;
    if(KMP(b->data.info,name) != -1)
        return b;
    if(b->brother)
    {
        q=keySearch(b->brother,name);   //在兄弟中找
        if(q)
            return q;
    }
    if(b->child)
    {
        q=keySearch(b->child,name);     //在孩子中找
        if(q)
            return q;
    }
    return NULL;
}

void printStory(BTNode *&head)//按关键字查找
{
    BTNode *key;
    char story[50];
    printf("请输入关键字或词:");
    scanf("%s",story);
    key = keySearch(head,story);
    print(key);
}

void menu()
{
    printf("1.添加家谱祖先\n");
    printf("2.添加孩子\n");
    printf("3.按姓名查询\n");
    printf("4.按事迹查询\n");
    printf("5.按姓名删除\n");
    printf("6.按姓名修改\n");
    printf("7.打印全部家族成员及其关系\n");
    printf("0.退出\n");
}
int main()
{
    BTNode *head;
    int m;
    while(1)
    {
        menu();
        printf("请输入选项:");
        scanf("%d",&m);
        switch(m)
        {
        case 1:
                head = createFirst();       //添加家谱祖先
                break;
        case 2:
                addChild(head);             //添加孩子
                break;
        case 3:
                printName(head);            //按姓名查询
                break;
        case 4:
                printStory(head);          //按事迹查询
                break;
        case 5:
                deleteName(head);           //按姓名删除
                break;
        case 6:
                alterName(head);            //按姓名修改
                break;
        case 7:
                printAll(head);             //列出全部家族成员及关系
                break;
        case 0:
                return 0;                    //退出
        }
    }
    return 0;
}

  

posted @ 2019-07-31 18:33  青衫客36  阅读(668)  评论(0编辑  收藏  举报