二叉树的应用:利用C语言编写简单的家谱管理系统

/*采用树型结构实现如下系统功能:
1)输入文件以存放最初家谱中各成员的信息。 成员的信息中均应包含以下内容:
姓名、出生日期、婚否、地址、健在否、死亡日期(若其已死亡)也可附加其它信息、但不是必需的。
2)实现数据的存盘和读盘。
3)以图形方式显示家谱。
4)显示第n代所有人的信息。
5)按照姓名查询,输出成员信息(包括其本人、父亲、孩子的信息)。
6)按照出生日期查询成员名单。
7)输入两人姓名,确定其关系。
8)某成员添加孩子。
9)删除某成员(若其还有后代,则一并删除)。
10)修改某成员信息。
11)按出生日期对家谱中所有人排序。
12)打开一家谱时,提示当天生日的健在成员。
测试要求:
1)建立至少10个成员的数据,以较为直观的方式显示结果,并提供文稿形式以便检查。
2)对界面的要求是:有合理的提示,每个功能可以设立菜单,根据提示,可以完成相关的功能要求。

注:有关文件的操作我做的不好,另外图形化界面做的不太好,增加孩子的时候空格不好控制,这是CodeBlocks的硬伤
*/
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<fstream>
#define MAXSIZE 100
using namespace std;
typedef struct Infomation{
    char name[20];
    char birth[20];
    int wedding;
    char add[20];
    int health;
    char death_date[20];
}Info;
typedef struct bnode{
    Info person;
    struct bnode *lchild,*rchild;
}BNode,*BiTree;

typedef struct{   //循环队列的定义
    BiTree queue[MAXSIZE];
    int front,rear;
}Queue;
void InitQ(Queue &Q)  //初始化
{
    Q.front=Q.rear=0;
}

void EnQueue(Queue &Q,BiTree e)  //入队
{
    Q.rear=(Q.rear+1)%MAXSIZE;
    Q.queue[Q.rear]=e;
}

void DeQueue(Queue &Q,BiTree &e)  //出队
{
    Q.front=(Q.front+1)%MAXSIZE;
    e=Q.queue[Q.front];
}

int QEmpty(Queue Q)  //判队空
{
    return Q.front==Q.rear;
}

int QFull(Queue Q)  //判队满
{
    if((Q.rear+1)%MAXSIZE==Q.front)
        return 1;
    return 0;
}
void new_left(BiTree p,Info info)
{
    BiTree q=(BiTree)malloc(sizeof(BNode));
    q->person=info;
    q->lchild=q->rchild=NULL;
    p->lchild=q;
}
void new_right(BiTree p,Info info)
{
    BiTree q=(BiTree)malloc(sizeof(BNode));
    q->person=info;
    q->lchild=q->rchild=NULL;
    p->rchild=q;
}
BiTree create()
{
    struct Infomation human[11]={{"John","19000511",1,"nefu",0,"19800401"},
                                {"Jack","19200721",1,"hit",0,"19900402"},
                                {"Mary","19230526",1,"mit",0,"19981221"},
                                {"Tom","19440501",1,"bit",0,"20080419"},
                                {"Lily","19480711",0,"nefu",0,"20010201"},
                                {"Ben","19480505",1,"hit",0,"20070401"},
                                {"June","19490541",1,"baidu",0,"20141111"},
                                {"Mark","19600430",0,"nefu",1,"I am alive!"},
                                {"Lucy","19760301",0,"jingdong",1,"I am alive!"},
                                {"Steven","19770519",1,"alibaba",1,"I am alive!"},
                                {"Ann","20000101",0,"nefu",1,"I am alive!"}};
    BiTree bt;
    bt=(BiTree)malloc(sizeof(BNode));
    bt->person=human[0];
    bt->lchild=bt->rchild=NULL;
    new_left(bt,human[1]);
    new_right(bt,human[2]);
    new_left(bt->lchild,human[3]);
    new_right(bt->lchild,human[4]);
    new_left(bt->rchild,human[5]);
    new_right(bt->rchild,human[6]);
    new_left(bt->lchild->lchild,human[7]);
    new_right(bt->lchild->lchild,human[8]);
    new_left(bt->rchild->rchild,human[9]);
    new_right(bt->rchild->rchild->lchild,human[10]);
    return bt;
}
void output(BiTree p)//输出某结点的信息
{
    printf("%-7s%-7s%7d%12s%10d%17s\n",p->person.name,p->person.birth,p->person.wedding,p->person.add,p->person.health,p->person.death_date);
}
void level(BiTree t) //层次遍历家谱图
{
    BiTree q[20],p;
    int front,rear;
    front=rear=0;
    printf("姓名   出生日期     婚否      地址      健在否       死亡日期\n");
    if(t)
    {
        rear++;
        q[rear]=t;
        while(front!=rear)
        {
            front=(front+1)%20;
            p=q[front];
            output(p);
            if((rear+1)%20!=front&&p->lchild!=NULL)
            {
                rear=(rear+1)%20;
                q[rear]=p->lchild;
            }
            if((rear+1)%20!=front&&p->rchild!=NULL)
            {
                rear=(rear+1)%20;
                q[rear]=p->rchild;
            }
        }
    }
}
void show_which_level(BiTree p,int n) //层次遍历家谱的第n层
{
    static int depth=0;
    depth++;
    if(p)
    {
        if(depth==n)
        {
            output(p);
        }
        show_which_level(p->lchild,n);
        show_which_level(p->rchild,n);
    }
    depth--;
}
BiTree Parent(BiTree bt,BiTree p)  //找到结点p的双亲并返回
{
    BiTree l_result,r_result;
    if (!bt||bt==p)
        return NULL;
    if (bt->lchild==p||bt->rchild==p)
        return bt;
    else
    {
        l_result=Parent(bt->lchild,p);
        r_result=Parent(bt->rchild,p);
        return l_result?l_result:(r_result?r_result:NULL);
    }
}
BiTree search_name(BiTree bt,char na[])  //通过名字找到结点并返回
{
    BiTree l_result,r_result;
    if(!bt)
        return NULL;
    if(strcmp(bt->person.name,na)==0)
        return bt;
    else
    {
        l_result=search_name(bt->lchild,na);
        r_result=search_name(bt->rchild,na);
        return l_result?l_result:(r_result?r_result:NULL);
    }
}
void search_child(BiTree p,BiTree child[])  //找到结点p的孩子存到指针数组child[]中
{
    child[0]=child[1]=NULL;
    if(p->lchild!=NULL)
        child[0]=p->lchild;
    if(p->rchild!=NULL)
        child[1]=p->rchild;
}
void search_3dai(BiTree bt)  //显示三代的信息
{
    char na[20];
    BiTree parent,node,child[2];
    printf("请输入你想查找的那个人的姓名:\n");
    scanf("%s",na);
    node=search_name(bt,na);
    parent=Parent(bt,node);
    search_child(node,child);
    printf("你查找的这个人的信息为:\n\n");
    printf("姓名   出生日期     婚否      地址      健在否       死亡日期\n");
    output(node);
    printf("他的父亲结点的信息为:\n");
    output(parent);
    if(child[0]!=NULL)
    {
        printf("他的左孩子的信息为:\n");
        output(child[0]);
    }
     if(child[1]!=NULL)
    {
        printf("他的右孩子的信息为:\n");
        output(child[1]);
    }
}
BiTree search_birth(BiTree bt,char bir[])  //通过生日找到结点并返回
{
    BiTree l_result,r_result;
    if(!bt)
        return NULL;
    if(strcmp(bt->person.birth,bir)==0)
        return bt;
    else
    {
        l_result=search_birth(bt->lchild,bir);
        r_result=search_birth(bt->rchild,bir);
        return l_result?l_result:(r_result?r_result:NULL);
    }
}
void search_birthday(BiTree bt)  //输出生日信息
{
    BiTree p;
    char bir[20];
    printf("请输入你想查找的那个人的生日:\n");
    scanf("%s",bir);
    p=search_birth(bt,bir);
    printf("你想查找的那个人的信息为:\n");
    printf("姓名   出生日期     婚否      地址      健在否       死亡日期\n");
    output(p);
}

int is_the_same_father(BiTree bt,BiTree p,BiTree q)  //判断结点p和q是否是同一个爸爸,如果是返回1,否则返回0
{
    BiTree f1,f2;
    f1=Parent(bt,p);
    f2=Parent(bt,q);
    if(f1==f2)
        return 1;
    else
        return 0;
}
void ralationship(BiTree bt)   //判断两个人的关系
{
    char name1[20],name2[20];
    BiTree s1,s2,f1,f2;
    printf("请输入第一个人的姓名:\n");
    scanf("%s",name1);
    printf("请输入第二个人的姓名:\n");
    scanf("%s",name2);
    s1=search_name(bt,name1);
    s2=search_name(bt,name2);
    f1=Parent(bt,s1);
    f2=Parent(bt,s2);
    if(is_the_same_father(bt,s1,s2)==1)
        printf("他们是亲兄弟关系\n");
    else if(is_the_same_father(bt,f1,f2)==1)
        printf("他们是堂兄弟关系\n");
    else if(s1->lchild==s2)
        printf("%s是%s的左孩子\n",s2->person.name,s1->person.name);
    else if(s1->rchild==s2)
        printf("%s是%s右孩子\n",s2->person.name,s1->person.name);
    else if(s2->lchild==s1)
        printf("%s是%s的左孩子\n",s1->person.name,s2->person.name);
    else if(s2->rchild==s1)
        printf("%s是%s的右孩子\n",s1->person.name,s2->person.name);
    else
        printf("这两个人关系太远啦!\n");
}
void add(BiTree &bt)   //让一个结点拥有孩子
{
    char na[20];
    int i;
    BiTree p;
    Info new_child;
    printf("请输入你想让其拥有孩子的那个人的名字:\n");
    scanf("%s",na);
    p=search_name(bt,na);
    printf("你是想让他有左孩子呀,还是右孩子呀?左孩子请按1,右孩子请按0:\n");
    scanf("%d",&i);
    switch(i)
    {
        case 1:
            if(p->lchild!=NULL)
            {
                printf("添加失败!人家已经有左孩子了!\n");
                break;
            }
            else
            {
                printf("请输入新孩子的姓名:\n");
                scanf("%s",new_child.name);
                printf("请输入新孩子的出生日期:\n");
                scanf("%s",new_child.birth);
                printf("新孩子结婚了吗,结婚请按1,没有结婚请按0:\n");
                scanf("%d",&new_child.wedding);
                printf("请输入新孩子的地址:\n");
                scanf("%s",new_child.add);
                printf("新孩子健在吗?健在请按1,死了请按0:\n");\
                scanf("%d",&new_child.health);
                printf("如果新孩子死了,请输入死亡日期,不然请输入-1:\n");
                scanf("%s",new_child.death_date);
                if(strcmp(new_child.death_date,"-1")==0)
                    strcpy(new_child.death_date,"I am alive!");
                new_left(p,new_child);
            }
            break;
        case 2:
            if(p->rchild!=NULL)
            {
                printf("添加失败!人家已经有右孩子了!\n");
                break;
            }
            else
            {
                printf("请输入新孩子的姓名:\n");
                scanf("%s",new_child.name);
                printf("请输入新孩子的出生日期:\n");
                scanf("%s",new_child.birth);
                printf("新孩子结婚了吗,结婚请按1,没有结婚请按0:\n");
                scanf("%d",&new_child.wedding);
                printf("请输入新孩子的地址:\n");
                scanf("%s",new_child.add);
                printf("新孩子健在吗?健在请按1,死了请按0:\n");\
                scanf("%d",&new_child.health);
                printf("如果新孩子死了,请输入死亡日期,不然请输入-1:\n");
                printf("%s",new_child.death_date);
                if(strcmp(new_child.death_date,"-1")==0)
                    strcpy(new_child.death_date,"I am alive!");
                new_right(p,new_child);
            }
            break;
        default:
            printf("你的输入有误!\n");
            break;
    }
}
void delete_name(BiTree &bt) //删除一个结点和他的孩子们孙子们
{
    char na[20];
    BiTree p,f;
    printf("请输入你想删除的那个人的姓名,删除之后他的孩子孙子们也将一并删除!\n");
    scanf("%s",na);
    p=search_name(bt,na);
    f=Parent(bt,p);
    if(f!=NULL)
    {
        if(f->lchild==p)
        {
            f->lchild=NULL;
            free(p);
        }
        if(f->rchild==p)
        {
            f->rchild=NULL;
            free(p);
        }
    }
    else
    {
        bt=NULL;
    }
}

void show_family(BiTree bt) //显示家谱
{
    Queue Q1,Q2;
    int i=0;
    BiTree e;
    InitQ(Q1);
    InitQ(Q2);
    if(bt!=NULL)
    {
        EnQueue(Q1,bt);
        while(!QEmpty(Q1))
        {
            while(!QEmpty(Q1))
            {
                DeQueue(Q1,e);
                EnQueue(Q2,e);
            }
            i++;
            if(i==1)
                printf("第%d代:         ",i);
            if(i==2)
                printf("第%d代:      ",i);
            if(i==3)
                printf("第%d代:   ",i);
            if(i==4)
                printf("第%d代:",i);
            if(i==5)
                printf("第%d代:                ",i);
            while(!QEmpty(Q2))
            {
                DeQueue(Q2,e);
                printf("%s ",e->person.name);
                if(!QFull(Q1)&&e->lchild!=NULL)
                    EnQueue(Q1,e->lchild);
                if(!QFull(Q1)&&e->rchild!=NULL)
                    EnQueue(Q1,e->rchild);
            }
            puts("");

        }
    }
}

void update(BiTree bt)
{
    char na[20];
    BiTree p;
    printf("请输入你想修改孩子的姓名:\n");
    scanf("%s",na);
    p=search_name(bt,na);
    printf("请输入修改过后的姓名:\n");
    scanf("%s",p->person.name);
    printf("请输入修改过后的出生日期:\n");
    scanf("%s",p->person.birth);
    printf("请问修改过后的那个人结婚了吗?结婚请输入1,没结婚请输入0:\n");
    scanf("%d",&p->person.wedding);
    printf("请输入修改过后的住址:\n");
    scanf("%s",p->person.add);
    printf("请问修改过后的那个人健在吗?健在请输入1,死了请输入0:\n");
    scanf("%d",&p->person.health);
    printf("如果修改过后那个人死了,请输入死亡日期,否则请输入-1:\n");
    scanf("%s",p->person.death_date);
    if(strcmp(p->person.death_date,"-1")==0)
        strcpy(p->person.death_date,"I am alive!");
}

void transport(BiTree bt,char bir[][20],int &x)  //把家谱中所有人的生日传参给二维数组bir[][]
{
    if(bt)
    {
        strcpy(bir[x++],bt->person.birth);
        transport(bt->lchild,bir,x);
        transport(bt->rchild,bir,x);
    }
}

void sort_birth(BiTree bt,char bir[][20],int n)//将二维数组升序排序并输出
{
    char t[20];
    int i,j;
    BiTree p;
    for(i=0;i<n-1;i++)
        for(j=i+1;j<n;j++)
            if(strcmp(bir[i],bir[j])>0)
            {
                strcpy(t,bir[i]);
                strcpy(bir[i],bir[j]);
                strcpy(bir[j],t);
            }
    for(i=0;i<n;i++)
    {
        p=search_birth(bt,bir[i]);
        output(p);
    }
    puts("");
}

void menu()
{
    printf("\n1.从文件读取家族信息并显示\n");
    printf("2.保存家族信息并存盘\n");
    printf("3.显示家谱图\n");
    printf("4.层次遍历家谱图\n");
    printf("5.显示第n代人的所有信息\n");
    printf("6.按照姓名查询,输出成员信息(包括其本人、父亲、孩子的信息)\n");
    printf("7.按照出生日期查询成员名单\n");
    printf("8.输入两人姓名,确定其关系\n");
    printf("9.给某成员添加孩子\n");
    printf("10.删除某成员(若其还有后代,则一并删除)\n");
    printf("11.修改某成员信息\n");
    printf("12.按出生日期对家谱中所有人排序\n");
    printf("13.退出系统\n");
}

int main()
{
    BiTree bt;
    int wedding1,health1,i,j,n,x=0;
    char bir[20][20],name1[20],birth1[20],add1[20],death_date1[20];
    printf("欢迎来到家谱管理系统!\n");
    bt=create();
LL1:menu();
    printf("\n请输入你的选择:\n");
    scanf("%d",&i);
    switch(i)
    {
        case 1:
            {
                ifstream fin("zupu.txt");
                printf("从文件里读出来的信息是:\n");
                printf("姓名   出生日期     婚否      地址      健在否       死亡日期\n");
                for(j=0;j<11;j++)
                {
                    fin>>name1>>birth1>>wedding1>>add1>>health1>>death_date1;
                    printf("%-7s%-7s%7d%12s%10d%17s\n",name1,birth1,wedding1,add1,health1,death_date1);
                }
                fin.close();
                goto LL1;
                break;
            }
        case 2:
            {
                ofstream fout("zupu.txt");
                struct Infomation man[11]={{"John","19000511",1,"nefu",0,"19800401"},
                                           {"Jack","19200721",1,"hit",0,"19900402"},
                                           {"Mary","19230526",1,"mit",0,"19981221"},
                                           {"Tom","19440501",1,"bit",0,"20080419"},
                                           {"Lily","19480711",0,"nefu",0,"20010201"},
                                           {"Ben","19480505",1,"hit",0,"20070401"},
                                           {"June","19490541",1,"baidu",0,"20141111"},
                                           {"Mark","19600430",0,"nefu",1,"I_am_alive!"},
                                           {"Lucy","19760301",0,"jingdong",1,"I_am_alive!"},
                                           {"Steven","19770519",1,"alibaba",1,"I_am_alive!"},
                                           {"Ann","20000101",0,"nefu",1,"I_am_alive!"}};
                for(j=0;j<11;j++)
                    fout<<man[j].name<<" "<<man[j].birth<<" "<<man[j].wedding<<" "<<man[j].add<<" "<<man[j].health<<" "<<man[j].death_date<<endl;
                fout.close();
                printf("保存成功!\n");
                goto LL1;
                break;
            }
        case 3:show_family(bt);
            goto LL1;
            break;
        case 4:
            level(bt);
            goto LL1;
            break;
        case 5:
            printf("你想查找第几代的信息呀?\n");
            scanf("%d",&n);
            show_which_level(bt,n);
            goto LL1;
            break;
        case 6:
            search_3dai(bt);
            goto LL1;
            break;
        case 7:
            search_birthday(bt);
            goto LL1;
            break;
        case 8:
            ralationship(bt);
            goto LL1;
            break;
        case 9:
            add(bt);
            show_family(bt);
            level(bt);
            goto LL1;
            break;
        case 10:
            delete_name(bt);
            show_family(bt);
            level(bt);
            goto LL1;
            break;
        case 11:
            update(bt);
            show_family(bt);
            level(bt);
            goto LL1;
            break;
        case 12:
            transport(bt,bir,x);
            sort_birth(bt,bir,x);
            goto LL1;
            break;
        case 13:
            printf("谢谢你的使用,再见啦!\n");
            exit(0);
        default:
            printf("你的输入有误,请重新输入!\n");
            goto LL1;
            break;
    }
}
  • 79
    点赞
  • 342
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
这是一个比较复杂的需求,需要用到多个模块和技术。以下是一个大致的实现思路: 1. 实现用户登录和权限控制:可以使用Spring Security框架来实现。在其中定义两个角色:普通用户和超级管理员,并对应不同的权限(查询权限和修改权限)。用户登录后,会根据角色的不同自动跳转到对应的页面。 2. 实现家谱信息的存储:可以使用文本文件来存储家谱信息,每个成员信息之间用特定的符号分隔。同时也可以考虑使用数据库来存储家谱信息,方便查询和排序。 3. 实现家谱信息的查询:可以使用Java IO或者第三方库来读取家谱信息文件,并根据用户输入的查询条件进行筛选和输出。查询条件包括姓名、出生日期等。同时,为了方便显示家族成员的辈分关系,可以将家谱信息存储为树形结构,并使用递归算法进行查询。 4. 实现家谱信息的排序:可以使用Java自带的Collections.sort()方法,或者自己实现快速排序等算法。排序的依据是成员的出生日期。 5. 实现生日提醒功能:可以使用Java自带的日期处理类,获取当前日期,并遍历家谱信息,查找今天生日的健在成员。 6. 实现直系祖先后裔关系查询:可以先按照姓名查询到两个成员的信息,然后根据家谱信息中的父子关系,递归查找两个成员是否存在直系祖先后裔关系。 以上是一个大致的实现思路,具体实现过程中还需要注意一些细节和问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值