C++实现家谱图

C++实现家谱图`

#include<iostream>
#include<fstrea`#include<stdio.h>
#include<queue>
#include<string.h>
#include<stdlib.h>
using namespace std;

class Node{
public:
   char name[6];//姓名
   int birth;//出生日期
   int marry;//0为未婚
   int now;//表示存活情况,0表示活着,日期表示死亡时间
   int gene;//代数
    Node *fc;
    Node *fb;
    Node *fa;
    Node(){fc=fb=fa=nullptr;}
};

class Tree{
public:
    Node *root;
    virtual ~Tree(){};
    void Destroy(Node *r)
    {
        root=nullptr;
    }
    Tree()
    {
         int lis[50];//父亲的下标,父亲数组
         int ls[20];
         int num,numx,k;
         queue<Node*> q1;
         numx=num=k=0;
         ifstream fin("test.txt");
         fin>>num;            //输入结点的个数
         for(int i=0;i<num;i++){fin>>lis[i];}//输入一个数组,数组元素为每个结点的父亲的下标,第一个为-1

         Node* p =new Node;    //根节点
         fin>> p->name >> p->birth >> p->marry >> p->now;
         root = p;root->gene=1;//定义root的代数为1
         Node* fath;  Node* q=root;//定义当前父亲,当前上一个结点
         q1.push(root);

         //求得作为父亲的结点下表ls[i],共numx个
         for(int i=1,j=0;i<num;i++) if(lis[i]>j){ls[numx++]=lis[i];j=lis[i];}

         for(int i=1;i<num;i++)
         {    //从第二个开始
            Node* p =new Node;         //定义结点,输入数据
            fin>> p->name >> p->birth >> p->marry >> p->now;

            //找到父亲,入队操作
            if(ls[k]==i) {q1.push(p);k++;}
             //录入数据时,子代数为父亲加一
            if(lis[i]>lis[i-1]){fath=q1.front();q1.pop();fath->fc=p;p->gene=fath->gene+1;p->fa=fath;q=p;}  //如果数字变大,则出队找新的fath,改变当前结点//可以添加老爸
            else {q->fb=p;p->gene=fath->gene+1;p->fa=fath;q=p;}       //如果数字一样,即此时为上个结点的兄弟
         }
         cout<<"从test.txt中读取信息并成功创建家谱!"<<endl<<endl;
    }
};
void shown(Node* m)
{
    cout<<m->name<<' '<<m->gene;
    if(m->fc!=nullptr) {shown(m->fc);};
    if(m->fb!=nullptr)shown(m->fb);

}

void showmain(Node* n,int x,int &m)//输出第x代
{
    if(n->gene==x) {cout<<n->name<<' ';m++;}
    if(n->fc!=nullptr)showmain(n->fc,x,m);
    if(n->fb!=nullptr)showmain(n->fb,x,m);
}
void shownn(Node* p,int x)
{
    int l=0;
    cout<<"第 "<<x<<" 代的成员如下:"<<endl;
    showmain(p,x,l);cout<<endl;
    cout<<"总共有 "<<l<<" 人"<<endl;
}




void addchild(Node* p,char a[],int &flag)//给指定名字的父亲添加孩子
{
    flag=0;
    if(strcmp(p->name,a)==0)
    {
        flag=1;
        Node* pa=p;//保留父亲结点指针
        if(p->fc!=nullptr)
        {
            p=p->fc;
            while(p->fb!=nullptr) p=p->fb;
            Node*na =new Node;
            cout<<"请输入孩子的姓名:";cin>>na->name;
            cout<<"请输入孩子的出生日期:";cin>>na->birth;
            cout<<"请输入孩子的婚姻状况:";cin>>na->marry;
            cout<<"请输入孩子的生命状态:";cin>>na->now;
            na->gene=pa->gene+1;   na->fa= pa; p->fb=na;
        }

        else
        {
            Node*na =new Node;
            cout<<"请输入孩子的姓名:";cin>>na->name;
            cout<<"请输入孩子的出生日期:";cin>>na->birth;
            cout<<"请输入孩子的婚姻状况:";cin>>na->marry;
            cout<<"请输入孩子的生命状态:";cin>>na->now;
            na->gene=pa->gene+1;   na->fa= pa; p->fc=na;
        }
    }
     if(p->fc!=nullptr&&flag==0)addchild(p->fc,a,flag);
     if(p->fb!=nullptr&&flag==0)addchild(p->fb,a,flag);
}

void child(Node* p){//获得该指针p的孩子,用于下面输出个人信息
  if(p->fc!=nullptr)
   {
      p=p->fc;
      while(p!=nullptr)
      {
         cout<<p->name<<' ';
         p=p->fb;
      }
   }
   else cout<<"无孩子";
}

void person(Node* p,char a[],int &flag)//输出个人信息
{
    flag=0;
    if(strcmp(p->name,a)==0)
    {
        flag=1;
        if(p->gene==1)
        {
             cout<<"姓名:"<<p->name<<endl;
             cout<<"出生日期:"<<p->birth<<endl;
             cout<<"婚姻状况:"<<p->marry<<endl;
             cout<<"生命状态:"<<p->now<<endl;
             cout<<"父亲的名字:我是祖宗= ="<<endl;
             cout<<"该家族里第 "<<p->gene<<" 代"<<endl;
             cout<<"他的孩子有:";
             child(p);
        }
        else
        {
            cout<<"姓名:"<<p->name<<endl;
            cout<<"出生日期:"<<p->birth<<endl;
            cout<<"婚姻状况:"<<p->marry<<endl;
            cout<<"生命状态:"<<p->now<<endl;
            cout<<"父亲的名字:"<<p->fa->name<<endl;
            cout<<"该家族里第 "<<p->gene<<" 代"<<endl;
            cout<<"他的孩子有:";
            child(p);
        }
        cout<<endl;
    }
    if(p->fc!=nullptr&&flag==0)person(p->fc,a,flag);
    if(p->fb!=nullptr&&flag==0)person(p->fb,a,flag);
}

void dele(Node* p,char a[],int &flagdel)//删除某节点及其子代
{
    flagdel=0;
    if(strcmp(p->name,a)==0)
    {
        flagdel=1;
        if(strcmp(p->fa->fc->name,p->name)==0) {p->fa->fc=p->fb;}
        else
        {
            Node* zan = p->fa->fc;//定义一个临时指针存储当前位置
            while(zan->fb!=p)zan=zan->fb;
            zan->fb=p->fb;
        }
    }
    if(p->fc!=nullptr&&flagdel==0)dele(p->fc,a,flagdel);
    if(p->fb!=nullptr&&flagdel==0)dele(p->fb,a,flagdel);
}

Node* getlock(Node*p,char a[],int &flaglock)//获得指定名字结点的指针
{   flaglock=0;
    if(strcmp(p->name,a)==0) {flaglock=1;return p;}
    queue<Node*> q2;
    if(p->fc!=nullptr)  p=p->fc;
    while(p!=nullptr||q2.empty()==0)
    {
        if(p!=nullptr)
        {
            if(p->fc!=nullptr) q2.push(p->fc); //有孩子则把孩子进队列
            if (strcmp(p->name,a)==0) {flaglock=1;return p;}  //访问节点本身
            p=p->fb;                           //指向他的兄弟
        }
        else  {p=q2.front();q2.pop();}//若p为空,则pop
    }

}

void getship(Node*p,char a[],char b[]){//输出两者关系
    int flaglock1=0,flaglock2=0;
    Node* p1=getlock(p,a,flaglock1);
    Node* p2=getlock(p,b,flaglock2);
    if(flaglock1==0) {cout<<a<<" 不是族谱成员!"<<endl;return;};
    if(flaglock2==0) {cout<<b<<" 不是族谱成员!"<<endl;return;};
    if(p1->gene==p2->gene)
    {
        if(strcmp(p1->fa->name,p2->fa->name)==0) cout<<"他们是亲兄弟"<<endl; else cout<<"他们是堂兄弟"<<endl;
    }
    else if (p1->gene-p2->gene==1)
    {
        if(strcmp(p1->fa->name,p2->name)==0) cout<<b<<" 是 "<<a<<" 的父亲"<<endl;
        else{cout<<b<<" 是 "<<a<<" 的叔伯"<<endl;}
    }
    else if (p1->gene-p2->gene==-1)
    {
        if(strcmp(p2->fa->name,p1->name)==0) cout<<a<<" 是 "<<b<<" 的父亲"<<endl;
        else{cout<<a<<" 是 "<<b<<" 的叔伯"<<endl;}
    }
    else if (p1->gene-p2->gene==2)
    {
        if(strcmp(p1->fa->fa->name,p2->name)==0) cout<<b<<" 是 "<<a<<" 的爷爷"<<endl;
        else{cout<<a<<" 是 "<<b<<" 的侄孙"<<endl;}
    }
    else if (p1->gene-p2->gene==-2)
    {
        if(strcmp(p2->fa->fa->name,p1->name)==0) cout<<a<<" 是 "<<b<<" 的爷爷"<<endl;
        else{cout<<b<<" 是 "<<a<<" 的侄孙"<<endl;}
    }
    else if (p1->gene-p2->gene==3)
    {
        if(strcmp(p1->fa->fa->fa->name,p2->name)==0) cout<<b<<" 是 "<<a<<" 的太爷爷"<<endl;
        else{cout<<a<<" 是 "<<b<<" 的重侄孙"<<endl;}
    }
    else if (p1->gene-p2->gene==-3)
    {
        if(strcmp(p2->fa->fa->fa->name,p1->name)==0) cout<<a<<" 是 "<<b<<" 的太爷爷"<<endl;
        else{cout<<b<<" 是 "<<a<<" 的重侄孙"<<endl;}
    }
    else
    {
        cout<<"这两个人的关系有点久远哦!直接拿祖宗和后辈处理吧!"<<endl;
        if(p1->gene<p2->gene)
            cout<<a<<" 是 "<<b<<" 的祖宗"<<endl;
        else
            cout<<b<<" 是 "<<a<<" 的祖宗"<<endl;
    }
}

void showall(Node* p){//打印家谱图
    cout<<p->name<<endl;
    queue<Node*> q2;
    int u=0;
    int flag1=0;//输出换行前的队列指针数
    int flag2=0;//当前队列中指针数目
    int fla[10];//记录上一层结点对应的是否有孩子,有孩子记1.否则0
    int flb[10];//记录这层
    int flag3=1;//记录上一层节点数目,为0时更新
    int flag4=0;//记录当前层结点数
    if(p->fc!=nullptr)  {p=p->fc;fla[0]=1;}
    while(p!=nullptr||q2.empty()==0)
     {
        if(p!=nullptr)
        {
            if(p->fc!=nullptr) {flb[flag4++]=1;q2.push(p->fc);flag2++;} //有孩子则把孩子进队列
            else flb[flag4++]=0;
            cout<<p->name<<' ';
            if(p->fb==nullptr)
            {
                cout<<')';
                if(flag1==0)
                {
                   cout<<endl;u=0;
                   for(int k=0;k<flag4;k++)fla[k]=flb[k];flag3=flag4;flag4=0;flag1=flag2-1;
                }
                else flag1--;
            }
            p=p->fb;
        }//指向他的兄弟
        else
        {
            if(u<flag3&&fla[u]==1) {p=q2.front();q2.pop();flag2--;u++;}
            else{cout<<')';u++;}
        } //若p为空,则pop
    }

}

void change(Node*p ,char a[])//修改某人信息
{
   int flaglock=0;
   Node* m =getlock(p,a,flaglock);
   if(flaglock==1)
   {
        cout<<"请输入新的信息 名字 生日 marry now:"<<endl;
        cout<<"姓名:";cin>>m->name;cout<<endl;
        cout<<"出生日期:";cin>>m->birth;cout<<endl;
        cout<<"婚姻状况:";cin>>m->marry;cout<<endl;
        cout<<"生命状态:";cin>>m->now;cout<<endl;
        cout<<"修改完成!"<<endl;
   }
   else {cout<<"不存在该人!"<<endl;}
}

void view(Node* n,int &m)//遍历家谱,什么也不做
{
     if(n!=nullptr) m++;
     if(n->fc!=nullptr)view(n->fc,m);
     if(n->fb!=nullptr)view(n->fb,m);

}
int personnum(Node* p)//获得总人数
{
    int l=0;
    view(p,l);
    return l;
}


void getfas(Node*p,int m[])
{
    //int m[50];//最大人数为50的父亲数组
    Node* s[50];//存储指针的数组;
    int k=0;//当前指针数组里的指针个数
    int num =personnum(p);//结点总数
    m[0]=-1;s[k++]=p;//
    queue<Node*> q2;

    if(p->fc!=nullptr)  {p=p->fc;}
    while(p!=nullptr||q2.empty()==0)
    {
         if(p!=nullptr)  {
            for(int f=0;f<k;f++)
            if(p->fa==s[f]) {m[k]=f;break;}//录入父亲数组
            s[k++]=p;//lu入指针数组
            if(p->fc!=nullptr) {q2.push(p->fc);} //有孩子则把孩子进队列
             p=p->fb;
            }
            else  {p=q2.front();q2.pop();} //若p为空,则pop
    }
}
void outdata(Node*p)//输出具体信息到屏幕
{
     queue<Node*> q2;
     cout<< p->name <<' '<< p->birth<<' ' << p->marry<<' ' << p->now<<endl;
    if(p->fc!=nullptr)  {p=p->fc;}
    while(p!=nullptr||q2.empty()==0)
     {
        if(p!=nullptr)
        {
            cout<< p->name <<' '<< p->birth<<' ' << p->marry<<' ' << p->now<<endl;
            if(p->fc!=nullptr) {q2.push(p->fc);} //有孩子则把孩子进队列
            p=p->fb;
        }
        else  {p=q2.front();q2.pop();} //若p为空,则pop
    }
}

void outfile(Node* p)
{
    //输出符号和父亲数组
    int m[50];
    ofstream fout;
    fout.open("test.txt");
    getfas(p,m);
    int v=personnum(p);
    fout<<v<<endl;
    if(p->fc==nullptr)
    {
        fout<<'-'<<'1'<<endl;
        fout<<p->name <<' '<< p->birth<<' ' << p->marry<<' ' << p->now<<endl;
    }
    else
    {
        for(int g=0;g<v;g++)
        fout<<m[g]<<' ';
        fout<<endl;
    //输出具体信息
        queue<Node*> q2;
        fout<< p->name <<' '<< p->birth<<' ' << p->marry<<' ' << p->now<<endl;
        if(p->fc!=nullptr)  {p=p->fc;}
        while(p!=nullptr||q2.empty()==0)
        {
            if(p!=nullptr)
            {
                fout<< p->name <<' '<< p->birth<<' ' << p->marry<<' ' << p->now<<endl;
                if(p->fc!=nullptr) {q2.push(p->fc);} //有孩子则把孩子进队列
                p=p->fb;
            }
            else  {p=q2.front();q2.pop();} //若p为空,则pop
        }
    }
    fout.close();
}
int main ()
{
    Tree c;
    /*int m[50];
    getfas(c.root,m);
    int v=personnum(c.root);
    cout<<v<<endl;
    for(int g=0;g<v;g++)
        cout<<m[g]<<' ';*/
    //showall(c.root);
    //shown(c.root);
    //shownn(c.root,3);//输出第3代
    //char a[5];
    //char b[5];
    //cout<<"输入名字A"<<endl;
    //cin>>a;
   // cout<<"输入名字B"<<endl;
    //cin>>b;
    //cout<<"start"<<endl  ;
    //person(c.root,a);
    //child(c.root);
    //dele(c.root,a);
    //addchild(c.root,a);
    //shownn(c.root,3);//输出第3代
    //cout<<"????"<<endl;
    //getship(c.root,a,b);
    //Node *u=getlock(c.root,a);
    //cout<<"nice"<<endl;
    //cout<<u->name<<endl;
    //change(c.root,a);
     //cout<<personnum(c.root);
    //outfile(c.root);
    cout<<"=================================="<<endl;
    cout<<"|Welcome To Use Genealogy System |"<<endl;
    cout<<"=================================="<<endl;
    cout<<endl;
    int n,flag3=0,flag4=0,flag5=0,flag6=0,flaglock=0;
    char a[8];
    char b[8];
    while(n!=0)
    {
        cout<<"1.显示家谱图"<<endl;
        cout<<"2.查找第m代人数及名字"<<endl;
        cout<<"3.姓名查询个人信息"<<endl;
        cout<<"4.输入两人姓名,确认关系"<<endl;
        cout<<"5.给某人添加孩子"<<endl;
        cout<<"6.删除某人"<<endl;
        cout<<"7.修改某人信息"<<endl;
        cout<<"8.输出到test.txt文件"<<endl;
        cout<<"9.输出所有人信息"<<endl;
        cout<<"0.退出"<<endl;
        cout<<"请输入n,进入功能模块"<<endl;
        cin>>n;
        switch(n){
        case 1: cout<<"-------------显示家谱图-------------"<<endl;
                if(c.root==nullptr)
                    cout<<"家谱为空!"<<endl;
                else if(c.root->fc==nullptr)
                    cout<<c.root->name<<endl;
                else
                    showall(c.root);
                cout<<"------------------------------------"<<endl;break;
        case 2: cout<<"---------查找第m代人数及名字--------"<<endl;
                int m;cout<<"请输入代数m:";cin >>m;cout<<endl;
                shownn(c.root,m);
                cout<<"------------------------------------"<<endl;break;
        case 3: cout<<"----------姓名查询个人信息----------"<<endl;
                cout<<"请输入姓名: "<<endl;cin>>a;
                person(c.root,a,flag3);
                if(flag3==0)
                    cout<<"不存在该人!"<<endl;
                cout<<"------------------------------------"<<endl;break;
        case 4: cout<<"-------输入两人姓名,确认关系-------"<<endl;
                cout<<"请输入第一人的姓名:";cin>>a;cout<<endl;
                cout<<"请输入第二人的姓名:";cin>>b;cout<<endl;
                getship(c.root,a,b);
                cout<<"------------------------------------"<<endl;break;
        case 5: cout<<"-----------给某人添加孩子-----------"<<endl;
                cout<<"请输入孩子的父亲的名字:";cin>>a;cout<<endl;
                addchild(c.root,a,flag5);
                if(flag5==1)
                    cout<<"添加孩子完成!"<<endl;
                else
                    cout<<"不存在该人,无法添加孩子!"<<endl;
                cout<<"------------------------------------"<<endl;break;
        case 6: cout<<"--------------删除某人--------------"<<endl;
                cout<<"请输入姓名:";cin>>a;cout<<endl;
                if(strcmp(a,c.root->name)==0)
                    {c.Destroy(c.root);flag6=1;}
                else
                    dele(c.root,a,flag6);
                if(flag6==0)
                    cout<<"不存在该人,删除失败!"<<endl;
                else
                    cout<<"删除成功!"<<endl;
                cout<<"------------------------------------"<<endl;break;
        case 7: cout<<"------------修改某人信息------------"<<endl;
                cout<<"请输入被修改人的姓名:";cin>>a;cout<<endl;
                change(c.root,a);
                cout<<"------------------------------------"<<endl;break;
        case 8: cout<<"---------输出到原test.txt文件--------"<<endl;
                if(c.root==nullptr)
                    {cout<<"家谱为空!"<<endl;cout<<"输出失败!"<<endl;}
                else
                    {outfile(c.root);cout<<"输出成功!"<<endl;}
                cout<<"------------------------------------"<<endl;break;
        case 9: cout<<"-----------输出所有人信息-----------"<<endl;
                if(c.root==nullptr)
                    cout<<"家谱为空!"<<endl;
                else
                    outdata(c.root);
                cout<<"------------------------------------"<<endl;break;
        }
        cout<<endl;
    }
    return 0;
}

------------------------test.txt
9
-1 0 0 2 2 2 4 4 6 
jack 1940 1 2020
kara 1963 1 0
kim  1970 1 2017
an 1982 0 0
mona 1985 1 0
sunny 1879 1 0
kaka 1999 1 0
cindy 2001 0 0
rain 2009 0 0

文档说明:看main函数即可,show部分为双亲表示法。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值