精华内容
下载资源
问答
  • 家族关系查询系统

    2015-11-08 14:47:58
    课程实践相关的C语言做的家族关系查询系统
  • 家族关系查询系统 1 课程设计介绍 1.1课程设计项目简介 家谱是一种以表谱形式记载一个以血缘关系为主体的家族世系繁衍和重要人物事迹的特殊图书载体家谱是中国特有的文化遗产是中华民族的三大文献之一属珍贵的人文...
  • 数据结构课程设计 家族关系查询系统 2020年4月19日 1课程设计介绍 1.1课程设计项目简介 家谱是一种以表谱形式记载一个以血缘关系为主 体的家族世系繁衍和重要人物事迹的特殊图书载体 家谱是中国特有的文化遗产是中华...
  • 家族关系查询系统 1 课程设计介绍 课程设计项目简介 家谱是一种以表谱形式记载一个以血缘关系为主体的家族世 系繁衍和重要人物事迹的特殊图书载体家谱是中国特有的文化 遗产是中华民族的三大文献之一属珍贵的人文...
  • c语言课程设计 家族关系查询 是你做课程设计的最佳参考 里面包含源代码和实验报告!!!!十分齐全!!!
  • 家族关系查询系统 家族关系查询系统 PAGE PAGE # 1课程设计介绍 1.1课程设计项目简介 家谱是一种以表谱形式记载一个以血缘关系为主体的家族世 系繁衍和重要人物事迹的特殊图书载体家谱是中国特有的文化 遗产是中华...
  • 家族关系查询系统(2021-9-22更新)

    千次阅读 多人点赞 2019-05-23 14:48:02
    家族关系查询系统 1.问题描述 建立家族关系数据库,实现对家族成员关系的相关查询。 2.基本要求 (1)建立家族关系并能存储到文件中; (2)实现家族成员的添加。 (3)可以查询家族成员的双亲、祖先、兄弟...

    最多的问题:1.如何运行?2.功能都什么?3.生成的文件都保存到哪里了?4.输入输出的格式是什么样的?

    1.打开编译器,复制粘贴运行,我用的是codeblocks,vs也是可以的,如不行,先看报错,尝试百度解决,如不行,下面评论我会回复。

    2.功能就是运行起来以后的展示出来的那么多,后面不会再增加新功能。

    3.cpp文件的相同目录下。

    4.

    文件名是家族名,格式输入如截图所示,如果不知道文件建在哪里,就使用第一个功能,让程序自动生成一个,你再进行修改。

     --------------------------------------------------------------------------------------------------------------------------------

    家族关系查询系统

    1.问题描述

    建立家族关系数据库,实现对家族成员关系的相关查询。

    2.基本要求

    (1)建立家族关系并能存储到文件中;

    (2)实现家族成员的添加。

    (3)可以查询家族成员的双亲、祖先、兄弟、孩子和后代等信息。

    3.扩展功能

    在家族关系查询中包含了许多查询功能,可通过输入不同的命令和参数有选择的实现各种查询。在编写程序时,可以加入修改成员信息的功能并能及时更新保存。

    数据结构的课程设计,用的三叉树,STL中的queue,使用文件形式输入。

    #include <string.h>
    #include<iostream>
    #include <malloc.h>
    #include<queue>
    #include<limits.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<io.h>
    #include<math.h>
    #include<ctype.h>
    #include<process.h>
    using namespace std;
    #define MAX 20
    typedef struct TriTNode
    {
        char data[MAX];
        struct TriTNode *parent;//双亲
        struct TriTNode *lchild;
        struct TriTNode *rchild;
    } Tree,*TreePt;
    
    
    char fname[MAX],family[50][MAX];// 全局变量
    
    Tree *Open(char familyname[MAX]);
    Tree *TreeCreate();
    Tree *Search(Tree *t,char str[]);
    void Append(Tree *t);
    void Ancestor(Tree *t);
    void AncestorPath(Tree *t);
    void Parent(Tree *t);
    void Generation(Tree *t);
    void Brothers(Tree *t,char str[]);
    void Consin(Tree *t);
    void Children(Tree *t);
    void InOrder(Tree *t);
    void allChildren(Tree *t);
    Tree *Create(char familyname[MAX]);
    
    
    
    int main()
    {
        char str[MAX];
        int flag,start =0;;
        Tree *temp,*tree=NULL;
        while(1)
        {
            printf("\t欢迎使用家族关系查询系统!\n");
            printf("\t 1.新建一个家庭关系:\n");
            printf("\t 2.打开一个家庭关系: \n");
            printf("\t 3.添加新成员的信息: \n");
            printf("\t 4.查找家族的祖先:\n");
            printf("\t 5.查找一个成员的祖先路径:\n");
            printf("\t 6.确定一个成员是第几代:\n");
            printf("\t 7.查找一个成员的双亲:\n");
            printf("\t 8.查找一个成员的兄弟:\n");
            printf("\t 9.查找一个成员的堂兄弟:\n");
            printf("\t10.查找一个成员的孩子:\n");
            printf("\t11.查找一个成员的子孙后代:\n");
            printf("\t12.退出系统: \n ");
            cin>>flag;
            if(!(flag==1||flag==2||flag==12)&&start==0)
            {
    
                printf("请先建立或打开一个家族关系!\n");
                continue;
            }
            start=1;
            switch(flag)              //根据flag标记调用函数
            {
            case 1:
                cout<<"请输入家族名氏"<<endl;
                getchar();
                gets(str);
                tree=Create(str);
                break;
            case 2:
                cout<<"请输入家族名氏"<<endl;
                getchar();
                gets(str);
                tree=Open(str);
                break;
            case 3:
                Append(tree);
                break;
            case 4:
                Ancestor(tree);
                break;
            case 5:
                cout<<"请输入成员名氏"<<endl;
                cin>>str;
                temp=Search(tree,str);
                if(!temp)             // 若不存在则返回
                {
                    printf("该成员不存在!\n");
                    continue;
                }
                AncestorPath(temp);
                break;
            case 6:
                cout<<"请输入成员名氏"<<endl;
                cin>>str;
                temp=Search(tree,str);
                if(!temp)             // 若不存在则返回
                {
                    printf("该成员不存在!\n");
                    continue;
                }
                Generation(temp);
                break;
            case 7:
                cout<<"请输入成员名氏"<<endl;
                cin>>str;
                temp=Search(tree,str);
                if(!temp)             // 若不存在则返回
                {
                    printf("该成员不存在!\n");
                    continue;
                }
                Parent(temp);
                break;
            case 8:
                cout<<"请输入成员名氏"<<endl;
                cin>>str;
                temp=Search(tree,str);
                if(!temp)             // 若不存在则返回
                {
                    printf("该成员不存在!\n");
                    continue;
                }
                Brothers(temp,str);
                break;
            case 9:
                cout<<"请输入成员名氏"<<endl;
                cin>>str;
                temp=Search(tree,str);
                if(!temp)             // 若不存在则返回
                {
                    printf("该成员不存在!\n");
                    continue;
                }
                Consin(temp);
                break;
            case 10:
                cout<<"请输入成员名氏"<<endl;
                cin>>str;
                temp=Search(tree,str);
                if(!temp)             // 若不存在则返回
                {
                    printf("该成员不存在!\n");
                    continue;
                }
                Children(temp);
                break;
            case 11:
                cout<<"请输入成员名氏"<<endl;
                cin>>str;
                temp=Search(tree,str);
                if(!temp)             // 若不存在则返回
                {
                    printf("该成员不存在!\n");
                    continue;
                }
                allChildren(temp);
                break;
            case 12:
                exit(1);
            }
        }
        return 0;
    }
    
    Tree *Create(char familyname[MAX])//建立家族关系并存入文件
    {
        int i=0;
        char ch,str[MAX];   //
        Tree *t;
        FILE *fp;
        strcpy(fname,familyname);  //以家族名为文本文件名存储
        strcat(fname,".txt");
        fp=fopen(fname,"r");       //以读取方式打开文件
        if(fp)                     // 文件已存在
        {
            fclose(fp);
            printf("%s 的家族关系已存在!重新建立请按“Y”,直接打开请按“N”\n",familyname);
            ch=getchar();
            getchar();
            if(ch=='N'||ch=='n')
            {
                t=Open(familyname);// 直接打开
                return t;
            }
        }
        if(!fp||ch=='Y'||ch=='y')     //重新建立,执行以下操作
        {
            fp=fopen(fname,"w");      //以写入方式打开文件,不存在则新建
            printf("请按层次输入结点,每个结点信息占一行\n");
            printf("兄弟输入结束以“@”为标志,结束标志为“#”\n★");
            gets(str);
            fputs(str,fp);
            fputc('\n',fp);
            strcpy(family[i],str);  //将成员信息存储到字符数组中*/
            i++;
            while(str[0]!='#')
            {
                printf("★");      //提示符提示继续输入
                gets(str);
                fputs(str,fp);     //写到文件中,每个信息占一行
                fputc('\n',fp);
                strcpy(family[i],str); //将成员信息存储到字符数组中
                i++;
            }
            fclose(fp);
            t=TreeCreate();  // 根据family数组信息创建三叉树*/
            printf("家族关系已成功建立!\n");
            return t;
        }
        return 0;
    }
    
    Tree *TreeCreate()
    {
        Tree *t,*tree,*root=NULL;
        queue<TreePt>q;
        int i=0,flag=0,start=0;
        char str[MAX];       // 存放family数组中信息
        strcpy(str,family[i]);
        i++;
        while(str[0]!='#')            //没遇到结束标志继续循环*/
        {
            while(str[0]!='@')    //没遇到兄弟输入结束标志继续
            {
                if(root==NULL)           // 空树
                {
                    root=(Tree *)malloc(sizeof(Tree));
                    strcpy(root->data,str);
                    root->parent=NULL;
                    root->lchild=NULL;
                    root->rchild=NULL;
    
                    q.push(root);
                    tree=root;
                }
                else                              //不为空树
                {
                    t=(Tree *)malloc(sizeof(Tree));
                    strcpy(t->data,str);
                    t->lchild=NULL;
                    t->rchild=NULL;
                    t->parent = q.front();// 当前结点的双亲为队头元素
    
                    q.push(t);
                    if(flag == 0)       //flag为0,当前结点没有左孩子
                        root->lchild=t;
                    else
                        root->rchild=t;   //flag为1,当前结点已有左孩子
                    root=t;                //root指向新的结点t
                }
                flag=1;             //标记当前结点已有左孩子
                strcpy(str,family[i]);
                i++;
            }
            if(start!=0)              //标记不是第一次出现“@”
            {
    
                q.pop();
                if(q.front())
                    root = q.front();
            }
            start=1;                       // 标记已出现过“@”
            flag=0;              //“@”后面的结点一定为左孩子
            strcpy(str,family[i]);
            i++;
        }
        return tree;
    }
    
    Tree *Open(char familyname[MAX])
    {
        int i=0,j=0;
        char ch;
        FILE *fp;
        Tree *t;
        strcpy(fname,familyname);  //以家族名为文本文件名存储
        strcat(fname,".txt");
        fp=fopen(fname,"r");            //以读取方式打开文件
        if(fp==NULL)                    //文件不存在
        {
            printf("%s 的家族关系不存在!\n",familyname);
            return NULL;
        }
        else
        {
            ch=fgetc(fp);              //按字符读取文件
            while(ch!=EOF)             //读到文件尾结束
            {
                if(ch!='\n')
                {
                    family[i][j]=ch;
                    j++;
                }
                else
                {
                    family[i][j]='\0';     //字符串结束标志
                    i++;              //family数组行下标后移
                    j=0;              //family数组列下标归零
                }
                ch=fgetc(fp);         //继续读取文件信息
            }
            fclose(fp);
            t=TreeCreate();  //调用函数建立三叉链表
            printf("家族关系已成功打开!\n");
            return t;
        }
    }
    Tree *Search(Tree *t,char str[])
    {
        Tree *temp;
        if(t==NULL)                //如果树空则返回NULL
            return NULL;
        else if(strcmp(t->data,str)==0) //如果找到返回该成员指针
            return t;
        else               //如果没找到遍历左右子树进行查找
        {
            temp=Search(t->lchild,str);
            if(temp)                    //结点不空则查找
                return(Search(t->lchild,str));
            else
                return(Search(t->rchild,str));
        }
    }
    void Append(Tree *t)  //添加成员
    {
        int i=0,j,parpos=1,curpos,num,end=0,count=-1;
        char chi[MAX],par[MAX];  //存储输入的孩子和其双亲结点
        Tree *tpar,*temp;
        FILE *fp;
        printf("请输入要添加的成员和其父亲,以回车分隔!\n. ");
        getchar();
        gets(chi);
        printf(". ");        //以点提示符提示继续输入
        gets(par);
        tpar=Search(t,par);  //查找双亲结点是否存在
        if(!tpar)
            printf("%s 该成员不存在!\n",par);
        else                 //存在则添加其孩子
        {
            temp=(Tree *)malloc(sizeof(Tree));
            temp->parent=tpar;
            strcpy(temp->data,chi);
            temp->lchild=NULL;
            temp->rchild=NULL;
            if(tpar->lchild)	                //成员存在左孩子
            {
                tpar=tpar->lchild; //遍历当前成员左孩子的右子树
                while(tpar->rchild)		  //当前结点右孩子存在
                    tpar=tpar->rchild;         //继续遍历右孩子
                tpar->rchild=temp;                //将新结点添加到所有孩子之后*/
            }
            else                       //没有孩子则直接添加
                tpar->lchild=temp;
            fp=fopen(fname,"w");         // 以写入方式打开文件
            if(fp)
            {
                while(strcmp(par,family[i])!=0&&family[i][0]!='#')
                {
                    if(family[i][0]!='@')
                        parpos++;
                    i++;
                }
                i=0;
                while(family[i][0]!='#')
                {
                    if(family[i][0]=='@')
                        count++;
                    if(count==parpos)
                        curpos=i;
                    i++;
                }
                if(count<parpos)
                {
                    num=parpos-count;
                    for(j=i; j<=i+num; j++)
                        strcpy(family[j],"@\0");
                    strcpy(family[i+num+1],"#\0");
                    strcpy(family[i+num-1],chi);
                    end=1;
                }
                else
                {
                    for(j=i; j>=curpos; j--)
                        strcpy(family[j+1],family[j]);
                    strcpy(family[curpos],chi);
                }
                if(end==1)
                    i=i+num;
                for(j=0; j<=i+1; j++)
                {
                    fputs(family[j],fp);
                    fputc('\n',fp);
                }
                fclose(fp);
                cout<<"添加新成员成功!"<<endl;
            }
            else
                cout<<"添加新成员失败!"<<endl;
        }
    }
    void Ancestor(Tree *t)            //祖先
    {
        printf("该家族的祖先为%s\n",t->data);
    }
    void AncestorPath(Tree *t)   //祖先路径
    {
        if(t->parent==NULL)     //若该成员为祖先,则直接输出
            printf("%s 无祖先!\n",t->data);
        else
        {
            printf("%s 所有祖先路径:%s",t->data,t->data);
            while(t->parent!=NULL) //若当前成员的双亲不是祖先,则继续查找
            {
                printf(" --> %s",t->parent->data);	//访问当前成员的双亲
                t=t->parent;
            }
            printf("\n");
        }
    }
    void Parent(Tree *t) //双亲
    {
        if(t->parent!=NULL)   //若该成员为祖先,则无双亲
            printf("%s 的双亲为%s\n",t->data,t->parent->data);
        else
            printf("%s 无双亲!\n",t->data);
    }
    
    
    void Generation(Tree *t)     //确定一个成员是第几代
    {
        int count=1;
        char str[MAX];
        strcpy(str,t->data);
        while(t->parent!=NULL)
        {
            count++;
            t=t->parent;
        }
        printf("%s 是第%d 代!\n",str,count);
    }
    void Brothers(Tree *t,char str[])    //查找兄弟
    {
        if(t->parent!=NULL)       //若该结点是祖先,则无兄弟
        {
            t=t->parent;  	                    //该结点的兄弟即为其双亲除该成员以外的所有孩子
            if(t->lchild&&t->lchild->rchild)    //当前结点的左孩子及其右孩子都存在
            {
                printf("%s 的所有兄弟有:",str);
                t=t->lchild;
                while(t)	        //遍历当前成员左孩子的右子树
                {
                    if(strcmp(t->data,str)!=0)  //遍历右子树,选择输出
                        printf("%s  ",t->data); //访问当前结点
                    t=t->rchild;
                }
                printf("\n");
            }
            else
                printf("%s 无兄弟!\n",str);
        }
        else
            printf("%s 无兄弟!\n",str);
    }
    void Consin(Tree *t)
    {
        int flag=0;
        Tree *ch=t;
        Tree *temp;
        if(t->parent&&t->parent->parent)//当前结点的双亲及其双亲都存在
        {
            t=t->parent->parent->lchild;//当前结点等于其祖先的第一个孩子
            while(t)	                //存在则继续查找
            {
                if(strcmp(t->data,ch->parent->data)!=0)
                {
                    if(t->lchild)	         //当前结点存在左孩子*/
                    {
                        temp=t->lchild;
                        while(temp)		               //遍历当前结点左孩子的右子树*/
                        {
                            if(strcmp(temp->data,ch->data)!=0)
                            {
                                if(!flag)
                                    printf("%s 的所有堂兄弟有:",ch->data);
                                printf("%s  ",temp->data);
                                flag=1;
                            }
                            temp=temp->rchild;            //继续遍历右孩子
                        }
                    }
                }
                t=t->rchild;                  //继续遍历右孩子
            }
            printf("\n");
        }
        if(!flag)
            printf("%s 无堂兄弟!\n",ch->data);
    }
    void Children(Tree *t)          //遍历左孩子
    {
        if(t->lchild)	               // 当前结点存在左孩子
        {
            printf("%s 的所有孩子有:",t->data);
            t=t->lchild;         //遍历当前成员左孩子的右子树*/
            while(t)
            {
                printf("%s  ",t->data);
                t=t->rchild;
            }
            printf("\n");
        }
        else
            printf("%s 无孩子!\n",t->data);
    }
    
    /* 中序遍历一棵树*/
    void InOrder(Tree *t)
    {
        if(t)
        {
            InOrder(t->lchild);
            printf("%s  ",t->data);
            InOrder(t->rchild);
        }
    }
    void allChildren(Tree *t)   //所有后代
    {
        if(t->lchild)              //当前结点存在左孩子
        {
            printf("%s 的所有子孙后代有:",t->data);
            InOrder(t->lchild);   //中序遍历当前结点的左右子树
            printf("\n");
        }
        else
            printf("%s 无后代!\n",t->data);
    }
    

    展开全文
  • 数据结构之家族亲属关系查询
  • 家族关系查询系统 1 课程设计介绍 1.1 课程设计项目简介 家谱是一种以表谱形式 记载一个以血缘关系为主体的家族世 系繁衍和重要人物事迹的特殊图书载体家谱是中国特有的文化 遗产是中华民族的三大文献之一属珍贵的...
  • 1.提前建立一个不少于30人的家族关系数据库并存储到文件当中 2.可以判断两个人的家族关系 3.可以实现成员的添加 4。可以进行子孙、双亲、堂兄等关系的查询
  • C++ 家族关系查询

    千次阅读 2020-01-22 12:42:48
    使用的语言:C++ 题目:家族关系查询

    前言

    这个家族关系查询的内容是博主课设的时候所做的,由于当时的技术不是很好,没有实现对家族树的层次遍历。
    如果你有兴趣的话,可以尝试一下对家族树的层次遍历实现,此代码已经放到了Github中。

    Github家族关系查询

    一、题目:

    41.家族关系查询
    建立家族关系数据库,实现对家族成员关闭的相关查询
    

    二、设计要求:

    (1)建立家族关系并能存储到文件中
    (2)实现家族成员的添加
    (3)可以查询家族成员的双亲、祖先、兄弟、孩子和后代等信息
    (4)该家族树宽度至少5,高度至少5
    

    三、数据结构:

    树状采用三叉链表实现,队列采用链式队列

    四、家族树报告

    家族树报告下载

    五、家族树代码

    在这里插入图片描述

    /*代码作者:小狐狸*/
    //
    //代码仍有部分缺陷,由于个人技术的原因,没有使用层次遍历实现打印所有成员信息
    //打印家族树和存入文件只会存储嫡系子代的信息
    //注:Findloc函数在本代码中的使用率很高,你可以使用该函数来查询某个成员在家族树中的位置(返回一个指针).
    //	  代码末尾有附带部分可用函数,若需要扩展功能时将函数放置main主函数之前即可
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    using namespace std;
    #define OK 1
    #define ERROR -1
    #define Max 200 //字符串数组最大值
    typedef struct TNode{
        string Wife;//妻子的姓名,若没有妻子时为空
        string Husband;//丈夫的姓名,若没有丈夫时为空
        struct TNode *parent;//双亲指针
        struct TNode *brother;//兄弟指针
        struct TNode *children;//孩子指针,仅指向最年长的孩子
    }tree,*Tree;//三叉链表
    int AddChild(Tree &Now,string Husbandname,string Wifename);//添加孩子到双亲节点Now
    int AddZuXian(Tree &T,string Husbandname,string Wifename);//添加祖先
    void CaiDanMain();//主菜单界面
    int CheckCunZai(Tree T);//判断某个节点是否有成员,有则返回OK,否则返回ERROR
    int CheckFile(string file);//判断文件是否已经存在,存在返回OK,否则返回ERROR
    int ChangeZuXian(Tree &T,string Husbandname,string Wifename);//修改家族的祖先
    int ChangeNow(Tree &Now,string Husbandname,string Wifename);//修改当前节点的信息,应保证当前节点存在
    void Findloc(Tree T,string &Husbandname,string &Wifename,Tree &Now);//通过丈夫和妻子的名字查找到对应的节点,Now为记录该节点的指针,递归循环(深度遍历)
    void PrintTree(Tree T);//将家族树的嫡系信息输出
    int PrintChild(Tree Now);//显示某个节点的所有孩子,Now为当前节点
    int PrintParent(Tree Now);//显示当前节点的双亲信息,Now为当前节点
    int PrintZuXian(Tree Now);//显示祖先,Now为当前节点
    int PrintBrother(Tree Now);//显示兄弟,Now为当前节点
    int PrintLater(Tree Now);//查询当前节点的所有嫡系后代的信息,不包括当前节点,Now为当前节点
    int InitTree(Tree &T);//初始化家族树
    int InputFile(Tree T,string file);//将家族树存入文件中
    int UploadFile(Tree &T,string file);//从已有的文件中将家族树信息覆盖
    
    int main()
    {
        Tree T;
        InitTree(T);//初始化
        while(1)
        {
            //fox存储用户输入的选项变量,初始值为0
            CaiDanMain();//主菜单显示
            int fox=0;//选项的选择
            cout<<"请选择: ";
            cin>>fox;
            if(CheckCunZai(T)==ERROR&&(fox>3&&fox<13))//若祖先不存在时先输入
            {
                cout<<"请先添加祖先!"<<endl;
                continue;
            }
            switch(fox)
            {
                case 0:return 0;//退出系统
                case 1://选择已有文件覆盖当前家族树
                    {
    
                        while(1){
                            //truth1变量值为1时表示文件导入成功,并退出循环;值为0时文件导入失败,显示提示信息。初始值为0
                            string file;
                            cout<<"请输入需要导入的家族姓氏: ";
                            cin>>file;
                            int truth1=0;
                            truth1=UploadFile(T,file);
                            if(truth1==OK)//从文件中导入家族树成功时
                            {
                                cout<<"导入成功!"<<endl;
                                break;
                            }
                            else
                            {
                                //truth2值为1时,继续输入家族姓氏;值为0时退出,初始值为1
                                cout<<"导入失败!退出按0,重新输入家族姓氏按1"<<endl;
                                int truth2=1;
                                cin>>truth2;
                                if(truth2==0) break;
                            }
                        }
                    }
                    break;
                case 2://将当前家族树存入文件中
                    {
                        //flag值为1时,重新输入家族姓氏;值为0时退出,初始值为1
                        string file;
                        int flag=1;
                        while(1)
                        {
                        cout<<"请输入家族姓氏作为文件名: ";
                        cin>>file;
                        if(CheckFile(file)==OK)//文件名存在时
                        {
                            cout<<"该家族姓氏已存在,退出按0,重新输入家族姓氏按1"<<endl;
                            cin>>flag;
                            if(flag==0)
                                break;
                            else continue;
                        }
                        if(CheckFile(file)==ERROR) break;
                        }
                        if(flag==0)//退出操作
                            break;
                        if(CheckFile(file)==ERROR)//文件名不存在时
                        {
                            InputFile(T,file);//将家族树导入文件
                            cout<<"操作成功!"<<endl;
                        }
                    }
                    break;
                case 3://添加祖先
                    {
                        if(CheckCunZai(T)==OK)//若祖先已存在时
                        {
                            cout<<"祖先已存在!"<<endl;
                        }
                        else//不存在时,输入祖先信息
                        {
                            string Husbandname,Wifename;
                            cout<<"祖父(祖先): ";
                            cin>>Husbandname;
                            cout<<"祖母(祖先): ";
                            cin>>Wifename;
                            AddZuXian(T,Husbandname,Wifename);
                        }
    
                    }
                    break;
                case 4://添加家族新成员
                    {
                        //flag1值为0时退出,为非0值时输入后代信息,初始值为0
                        int flag1=0;//若值为0时->退出此操作
                        string Fathername,Mothername,Husbandname,Wifename;
                        while(1)//当输入的父亲和母亲找到时退出循环
                        {
                            //flag2值为0时退出,为非0值时重新输入双亲信息,初始值为1
                            cout<<"父亲: ";
                            cin>>Fathername;
                            cout<<"母亲: ";
                            cin>>Mothername;
                            Tree truth=NULL;//为NULL时->显示提示信息,不为NULL时->输入成员信息
                            Findloc(T,Fathername,Mothername,truth);
                            if(truth==NULL)
                            {
                                int flag2=1;
                                cout<<"未找到双亲,退出按0,重新输入双亲按1"<<endl;
                                cin>>flag2;
                                if(flag2==0) break;
                                else continue;
                            }
                            else
                            {
                                cout<<"查找成功!可输入成员信息"<<endl;
                                flag1=1;//查找成功时赋值为1,执行输入成员信息
                                break;
                            }
                        }
                        if(flag1==0) break;//若为退出时,返回主界面
                        Tree Now;//临时指针
                        cout<<"丈夫: ";
                        cin>>Husbandname;
                        cout<<"妻子: ";
                        cin>>Wifename;
                        Findloc(T,Fathername,Mothername,Now);//寻找双亲的节点
                        AddChild(Now,Husbandname,Wifename);//添加孩子
                        while(1)
                        {
                            int flag3;//值为0时退出循环
                            cout<<"输入其兄弟按1,退出系统按0"<<endl;
                            cin>>flag3;
                            if(flag3==0)
                                break;
                            cout<<"丈夫: ";
                            cin>>Husbandname;
                            cout<<"妻子: ";
                            cin>>Wifename;
                            AddChild(Now,Husbandname,Wifename);//直接使用双亲节点
                        }
                    }
                    break;
                case 5://修改家族祖先
                    {
                        string Husbandname,Wifename;
                        cout<<"祖父(祖先): ";
                        cin>>Husbandname;
                        cout<<"祖母(祖先): ";
                        cin>>Wifename;
                        ChangeZuXian(T,Husbandname,Wifename);
                        cout<<"修改成功!"<<endl;
                    }
                    break;
                case 6://修改某个家族成员
                    {
                        //flag值为0时退出,值为1时重新输入成员信息并查找该成员,初始值为1
                        string Husbandname,Wifename;
                        int flag=1;
                        while(1){
                            //truth值为NULL时不存在该成员,不为NULL时成功找到成员信息,初始值为NULL
                            cout<<"丈夫(旧): ";
                            cin>>Husbandname;
                            cout<<"妻子(旧): ";
                            cin>>Wifename;
                            Tree truth=NULL;
                            Findloc(T,Husbandname,Wifename,truth);
                            if(truth)//存在该成员时
                            {
                                cout<<"查找成功!"<<endl;
                                break;
                            }
                            else//不存在该成员时
                            {
                                cout<<"查找失败,退出按0,重新输入按1!"<<endl;
                                cin>>flag;
                                if(flag==0) break;
                            }
                        }
                        if(flag==0)break;//退出操作
                        Tree Now;//临时指针
                        Findloc(T,Husbandname,Wifename,Now);
                        cout<<"丈夫(新): ";
                        cin>>Husbandname;
                        cout<<"妻子(新): ";
                        cin>>Wifename;
                        ChangeNow(Now,Husbandname,Wifename);
                    }
                    break;
                case 7://显示家族的祖先
                    {
                        PrintZuXian(T);
                    }
                    break;
                case 8://显示某个成员的双亲
                    {
                        //Now为NULL时,无成员信息;不为NULL时,有成员信息,初始值为NULL
                        string Husbandname,Wifename;
                        cout<<"丈夫: ";
                        cin>>Husbandname;
                        cout<<"妻子: ";
                        cin>>Wifename;
                        Tree Now=NULL;//临时指针
                        Findloc(T,Husbandname,Wifename,Now);
                        if(Now)
                            PrintParent(Now);
                        else cout<<"该成员信息不存在,无法找出双亲!"<<endl;;
                    }
                    break;
                case 9://显示兄弟
                    {
                        while(1){
                            //Now为NULL时,无成员信息;不为NULL时,有成员信息,初始值为NULL
                            string Husbandname,Wifename;
                            cout<<"丈夫: ";
                            cin>>Husbandname;
                            cout<<"妻子: ";
                            cin>>Wifename;
                            Tree Now=NULL;//临时指针
                            Findloc(T,Husbandname,Wifename,Now);
                            if(Now)//找到信息时
                            {
                                PrintBrother(Now);
                                break;
                            }
                            else//未找到成员信息时
                            {
                                //truth值为0时退出,非0时重新输入成员信息。初始值为1
                                cout<<"无该成员信息,退出按0,重新输入信息按1"<<endl;
                                int truth=1;
                                cin>>truth;
                                if(truth==0)
                                    break;
                            }
                        }
                    }
                    break;
                case 10://显示孩子
                    {
                        while(1)
                            {
                            //Now为NULL时,无成员信息;不为NULL时,有成员信息,初始值为NULL
                            string Husbandname,Wifename,Sonname,SonWifename;
                            cout<<"丈夫: ";
                            cin>>Husbandname;
                            cout<<"妻子: ";
                            cin>>Wifename;
                            Tree Now=NULL;//临时指针
                            Findloc(T,Husbandname,Wifename,Now);//找到节点位置
                            if(Now)//找到节点时
                            {
                                if(PrintChild(Now)==ERROR)
                                {
                                    cout<<"该成员无孩子!,退出按0,重新输入信息按1"<<endl;
                                    int truth=0;
                                    cin>>truth;
                                    if(truth==0)
                                        break;
                                }
                                else break;
                            }
                            else//未找到成员信息时
                            {
                                cout<<"无该成员信息,退出按0,重新输入信息按1"<<endl;
                                int truth=0;
                                cin>>truth;
                                if(truth==0)
                                    break;
                            }
                        }
                    }
                    break;
                case 11://显示所有后代
                    {
                        while(1)
                        {
                            //Now为NULL时,无成员信息;不为NULL时,有成员信息,初始值为NULL
                            string Husbandname,Wifename;
                            cout<<"丈夫: ";
                            cin>>Husbandname;
                            cout<<"妻子: ";
                            cin>>Wifename;
                            Tree Now=NULL;
                            Findloc(T,Husbandname,Wifename,Now);
                            if(Now)//存在时
                            {
                                PrintLater(Now);
                                break;
                            }
                            else//不存在该成员时
                            {
                                cout<<"无该成员信息,退出按0,重新输入信息按1"<<endl;
                                int truth=0;
                                cin>>truth;
                                if(truth==0)
                                    break;
                            }
                        }
                    }
                    break;
                case 12://显示家族树
                    {
    
                        PrintTree(T);
                    }
                    break;
                case 13://清屏操作
                    {
                        system("cls");
                    }
                    break;
                default:break;
            }
        }
        return 0;
    }
    int AddChild(Tree &Now,string Husbandname,string Wifename)//添加孩子到双亲节点Now
    {
        if(Now->children==NULL)//没有孩子时
        {
            Tree p;//创建新的节点
            p=new TNode;
            p->brother=NULL;
            p->children=NULL;
            p->Husband=Husbandname;
            p->Wife=Wifename;
            p->parent=Now;
            Now->children=p;
        }
        else//有孩子时
        {
            Tree now;
            now=Now->children;//指向主孩子
            while(now->brother!=NULL)//在兄弟中进行循环操作
                now=now->brother;
            Tree p;//创建新的节点
            p=new TNode;
            p->brother=NULL;
            p->children=NULL;
            p->Husband=Husbandname;
            p->Wife=Wifename;
            p->parent=Now;
            now->brother=p;//now此时为末位的兄弟节点
        }
        return OK;
    }
    int AddZuXian(Tree &T,string Husbandname,string Wifename)//添加祖先
    {
        Tree t;
        t=T;
        t->Husband=Husbandname;
        t->Wife=Wifename;
        t->brother=NULL;
        t->parent=NULL;
        t->children=NULL;
        return OK;
    }
    
    void CaiDanMain()//主菜单界面
    {
        cout<<endl;
        cout<<"-----------------------------<主菜单>----------------------------------"<<endl;
        cout<<"|    0 退出系统                                                        |"<<endl;
        cout<<"|    1 选择已有家族谱覆盖当前家族树                                    |"<<endl;
        cout<<"|    2 将嫡系家族树存入文件                                            |"<<endl;
        cout<<"|    3 添加祖先                                                        |"<<endl;
        cout<<"|    4 添加家族新成员[最年长的兄弟应首先输入,无妻子时请填写无]        |"<<endl;
        cout<<"|    5 修改家族祖先                                                    |"<<endl;
        cout<<"|    6 修改某个家族成员                                                |"<<endl;
        cout<<"|    7 显示家族的祖先                                                  |"<<endl;
        cout<<"|    8 显示某个成员的双亲                                              |"<<endl;
        cout<<"|    9 显示某个成员的兄弟                                              |"<<endl;
        cout<<"|   10 显示某个成员的孩子                                              |"<<endl;
        cout<<"|   11 显示某个成员的所有嫡系后代                                      |"<<endl;
        cout<<"|   12 显示嫡系家族树信息                                              |"<<endl;
        cout<<"|   13 清屏                                                            |"<<endl;
        cout<<"------------------------------------------------------------------------"<<endl;
        cout<<endl;
    }
    int CheckCunZai(Tree T)//判断某个节点是否有成员,有则返回OK,否则返回ERROR
    {
        Tree t;//临时指针
        t=T;
        if(t->Husband==""&&t->Wife=="")//对当前节点进行判断
        {
            return ERROR;
        }
        else return OK;
    }
    int CheckFile(string file)//判断文件是否已经存在,存在返回OK,否则返回ERROR
    {
        //flag为文件句柄,flag=串1.find(串2)
        //flag的返回值为string::npos时则表示串2不为串1的子串
        string::size_type flag;
        flag=file.find(".txt");
        if(flag==string::npos)//不含有后缀.txt时,添加后缀
            file+=".txt";
        FILE*fp;
        char filename[Max];
        strcpy(filename,file.c_str());
        if((fp=fopen(filename,"r"))==NULL)//不存在时返回ERROR
            return ERROR;
        else return OK;
    }
    int ChangeZuXian(Tree &T,string Husbandname,string Wifename)//修改家族的祖先
    {
        Tree t;
        t=T;
        if(t==NULL)
            return ERROR;
        t->Husband=Husbandname;
        t->Wife=Wifename;
        return OK;
    }
    int ChangeNow(Tree &Now,string Husbandname,string Wifename)//修改当前节点的信息,应保证当前节点存在
    {
        Tree now;
        now=Now;
        now->Husband=Husbandname;
        now->Wife=Wifename;
        return OK;
    }
    void Findloc(Tree T,string &Husbandname,string &Wifename,Tree &Now)//通过丈夫和妻子的名字查找到对应的节点,Now为记录该节点的指针,递归循环(深度遍历)
    {
        if(T==NULL)
            return;
        else
        {
            if(Husbandname==T->Husband&&Wifename==T->Wife)//若当前节点符合条件则Now指向当前节点
                Now=T;
            Findloc(T->children,Husbandname,Wifename,Now);//先对孩子进行遍历
            Findloc(T->brother,Husbandname,Wifename,Now);//后对兄弟进行遍历
        }
    }
    void PrintTree(Tree T)//将家族树的嫡系信息输出
    {
        //time表示第几代孩子,初始值为1
        Tree childs;//临时指针
        childs=T;
        int time=1;//第几代
        while(childs)//在孩子中进行循环
        {
            //cout<<"第"<<time<<"代:"<<endl;
            if(time!=1)
                cout<<"第"<<time<<"代:"<<endl;
            else//祖先节点时
                cout<<"第1代(祖先):"<<endl;
            Tree brothers;
            brothers=childs;
           while(brothers)//在兄弟中进行循环
           {
               cout<<brothers->Husband<<"(男) ";
               cout<<brothers->Wife<<"(女)"<<endl;
               brothers=brothers->brother;
           }
           time++;
           childs=childs->children;
        }
    }
    int PrintChild(Tree Now)//显示某个节点的所有孩子,Now为当前节点
    {
        cout<<endl;
        Tree k;
        if(Now->children==NULL)//没有孩子时,返回错误
        {
            return ERROR;
        }
        k=Now->children;
        cout<<"[孩子]"<<endl;
        while(k)//在兄弟中进行循环
        {
            cout<<k->Husband<<"(男) ";
            cout<<k->Wife<<"(女)"<<endl;
            k=k->brother;
        }
        return OK;
    }
    int PrintParent(Tree Now)//显示当前节点的双亲信息,Now为当前节点
    {
        cout<<endl;
        Tree now;
        now=Now;
        Tree parents=NULL;//parents为指向当前节点父母的指针
        if(now->parent==NULL)//若now为祖先节点时无父亲和母亲
        {
            cout<<"当前为祖先,没有双亲!"<<endl;
            return ERROR;
        }
        else parents=now->parent;
        cout<<"[父亲] ";
        cout<<parents->Husband<<endl;
        cout<<"[母亲] ";
        cout<<parents->Wife<<endl;
        return OK;
    }
    int PrintZuXian(Tree Now)//显示祖先,Now为当前节点
    {
        Tree k;//临时指针
        k=Now;
        while(k->parent!=NULL)//当往上循环到没有双亲的结点时为祖先
        {
            k=k->parent;
        }
        cout<<"[祖先] "<<endl;//祖先共有两个人
        cout<<k->Husband<<"(男) ";
        cout<<k->Wife<<"(女)"<<endl;
        return OK;
    }
    int PrintBrother(Tree Now)//显示兄弟,Now为当前节点
    {
        Tree k;//临时指针
        if(Now->parent==NULL)//若为祖先时
        {
            cout<<"祖先无兄弟!"<<endl;
            return ERROR;
        }
        k=Now->parent->children;//指向主孩子
        if(k->brother!=NULL)
        {
            cout<<"[兄弟] "<<endl;
        }
        else
            {
                cout<<"无兄弟!"<<endl;
                return ERROR;
            }
        while(k)//在节点的兄弟中进行循环输出
        {
            if(k->Husband!=Now->Husband&&k->Wife!=Now->Wife)//不输出当前节点的成员信息,仅输出兄弟的信息
            {
                cout<<k->Husband<<"(男) ";
                cout<<k->Wife<<"(女)"<<endl;
            }
            k=k->brother;
        }
        return OK;
    }
    int PrintLater(Tree Now)//查询当前节点的所有嫡系后代的信息,不包括当前节点,Now为当前节点
    {
        //time表示第几代孩子,初始值为1
        Tree k;
        if(Now->children==NULL)//无孩子时
        {
            cout<<"无后代信息"<<endl;
            return ERROR;
        }
        k=Now->children;
        int time=1;//表示第几代的孩子
        while(k)//孩子中循环
        {
            Tree p;
            p=k;
            cout<<"第"<<time<<"代:"<<endl;
            while(p)//兄弟中循环
            {
                cout<<p->Husband<<"(男) ";
                cout<<p->Wife<<"(女)"<<endl;
                p=p->brother;
            }
            time++;
            k=k->children;
        }
        return OK;
    }
    int InitTree(Tree &T)//初始化家族树
    {
        T=new TNode;//创建头节点
        T->Husband="";//初始化为空
        T->Husband="";
        T->children=NULL;
        T->brother=NULL;
        T->parent=NULL;
        return OK;
    }
    int InputFile(Tree T,string file)//将嫡系家族树存入文件中
    {
        //flag为文件句柄,flag=串1.find(串2)
        //若串2不为串1子串时,flag值为string::npos
        if(CheckFile(file)==OK)//文件已存在时返回错误
            return ERROR;
        string::size_type flag;
        flag=file.find(".txt");
        if(flag==string::npos)//没有后缀时添加后缀
            file+=".txt";
        FILE*fp;
        char filename[Max];
        char Husbandname[Max],Wifename[Max];
        char Fathername[Max],Mothername[Max];
        strcpy(filename,file.c_str());
        fp=fopen(filename,"w");
        Tree k;//孩子指针
        k=T;
        while(k)
        {
            Tree p;//兄弟指针
            p=k;
            while(p)
            {
                if((p->Husband!=T->Husband)&&(p->Wife!=T->Wife))//不为祖先节点时,将父母信息输入
                {
                    strcpy(Fathername,(p->parent->Husband).c_str());
                    strcpy(Mothername,(p->parent->Wife).c_str());
                    fprintf(fp,"%s ",Fathername);
                    fprintf(fp,"%s\t",Mothername);
                }
                strcpy(Husbandname,(p->Husband).c_str());
                strcpy(Wifename,(p->Wife).c_str());
                fprintf(fp,"%s ",Husbandname);//写入当前节点信息
                fprintf(fp,"%s\n",Wifename);
                p=p->brother;
            }
            k=k->children;
        }
        fprintf(fp,"#\n");//结束标志
        fclose(fp);//关闭文件
        return OK;
    }
    int UploadFile(Tree &T,string file)//从已有的文件中将家族树信息覆盖,若该文件不存在则返回ERROR
    {
        //flag为文件句柄,flag=串1.find(串2)
        //若串2不为串1子串时,flag值为string::npos
        string::size_type flag;//判断是否含有后缀.txt
        flag=file.find(".txt");
        if(flag==string::npos)//不含后缀时添加后缀.txt
            file+=".txt";
        char filename[Max];
        strcpy(filename,file.c_str());//将file复制到filename
        FILE*fp=fopen(filename,"r");//传入参数filename为字符数组类型
        if(fp==NULL)//文件不存在时
            return ERROR;
        char ZuFu[Max],ZuMu[Max];
        fscanf(fp,"%s",ZuFu);//将祖先信息存入
        fscanf(fp,"%s",ZuMu);
        string ZuFuname(ZuFu);
        string ZuMuname(ZuMu);
        AddZuXian(T,ZuFuname,ZuMuname);
        while(1)
        {
            char Father[Max],Mother[Max];
            char Husband[Max],Wife[Max];
            fscanf(fp,"%s",Father);
            string Fathername(Father);
            if(Fathername=="#")
                break;
            fscanf(fp,"%s",Mother);
            fscanf(fp,"%s",Husband);
            fscanf(fp,"%s",Wife);
            string Mothername(Mother);
            string Husbandname(Husband);
            string Wifename(Wife);
            Tree Now;
            Findloc(T,Fathername,Mothername,Now);//找到双亲节点
            if(Now)//存在双亲节点时
                AddChild(Now,Husbandname,Wifename);
        }
        fclose(fp);
        return OK;
    }
    /*
    int CountBrother(Tree Now,string Husbandname,string Wifename)//统计当前节点兄弟的个数
    {//可用
        int sum=0;//兄弟的个数
        Tree t;
        if(Now->parent==NULL)//当前为祖先时
            return 0;
        t=Now->parent->children;
        while(t)
        {
            if(t->Husband!=Husbandname&&t->Wife!=Wifename)
                sum++;
            t=t->brother;
        }
        return sum;
    }
    */
    /*
    int InputTree(Tree &T)//输入家族成员到家族树中
    {
        string Husbandname,Wifename,Fathername,Mothername;
        int flag1=2;//默认为需要重新输入双亲
        cout<<"祖父(祖先): "<<endl;
        cin>>Husbandname;
        cout<<"祖母(祖先): "<<endl;
        AddZuXian(T,Husbandname,Wifename);//添加覆盖祖先
        cout<<"家庭成员输入前,请输入其父母的信息!"<<endl<<endl;
        while(1)//根据父亲和母亲的名字输入家庭成员
        {
            if(flag1==2){//当输入新成员时需要重新输入父母信息
                cout<<"请输入父亲:"<<endl;
                cin>>Husbandname;
                cout<<"请输入母亲:"<<endl;
                cin>>Wifename;
            }
    
            Tree Now=NULL;//临时节点指针
            Findloc(T,Fathername,Mothername,Now);//从家族树中寻找符合父母亲的节点,用Now保存双亲节点
            int flag2=1;
            if(Now==NULL)//若家族树中无该双亲时
            {
                cout<<endl;
                cout<<"未查询到该双亲!"<<endl;
                cout<<"-------------------------"<<endl;
                cout<<"|    0 退出输入         |"<<endl;
                cout<<"|    1 重新输入双亲     |"<<endl;
                cout<<"|    2 打印已有家族树   |"<<endl;
                cout<<"-------------------------"<<endl;
                cout<<endl;
                cin>>flag2;
                int time=1,truth=1;//time表示第几代,truth表示递归中当前节点与前者的关系
                switch(flag2)
                {
                    case 0:return OK;
                    case 1:
                        {
                            cout<<"父亲: ";
                            cin>>Fathername;
                            cout<<"母亲: ";
                            cin>>Mothername;
                        }
                        break;
                    case 2:
                        {
                            int time=1,flag=1;
                            PrintTree(T,time,flag);
                        }
                        break;
                    default:break;
                }
                if(flag2==2) continue;
            }
            else cout<<"成功找到双亲!可输入成员信息"<<endl;
            string Husband,Wife;
            cout<<endl;
            cout<<"丈夫:"<<endl;
            cin>>Husband;
            cout<<"妻子:"<<endl;
            cin>>Wife;
            if(CheckChildren(Now)==ERROR)//若没有孩子时,直接插入到父母节点之后
            {
                AddChild(Now,Husband,Wife);
            }
            if(CheckChildren(Now)==OK)//若有孩子时,插入孩子的兄弟节点的后面
            {
                AddBrother(Now->children,Husband,Wife);//传入孩子节点
            }
            cout<<endl;
            cout<<"------------------------"<<endl;
            cout<<"|    0 退出输入        |"<<endl;
            cout<<"|    1 输入兄弟        |"<<endl;
            cout<<"|    2 输入新的成员    |"<<endl;
            cout<<"------------------------"<<endl<<endl;
            cin>>flag1;
            switch(flag1)
            {
                case 0:return OK;
                case 1:
                    {
    
                    }
                    break;
                case 2:
                    {
    
                    }
                    break;
                default:break;
            }
        }
        return OK;
    }*/
    /*
    int AddBrother(Tree &Now,string Husbandname,string Wifename)//添加新成员到兄弟节点之后,前提:Now应为其兄弟节点
    {
        Tree now;//临时指针
        now=Now;
        while(now->brother!=NULL)//从Now节点的孩子中找到需要插入的位置,即兄弟节点的最后一个位置
            now=now->brother;
        Tree p;
        p=new TNode;//创建一个节点
        p->Husband=Husbandname;
        p->Wife=Wifename;
        p->brother=NULL;
        p->parent=Now;
        p->children=NULL;
        //双亲节点的孩子指向最年长的孩子
    }
    */
    /*
    int CheckChildren(Tree Now)//检测某个节点是否有孩子,有则返回OK,否则返回ERROR
    {//可用
        Tree now;
        now=Now->children;
        if(now->Husband!=""&&now->Wife!="")
            return OK;
        else return ERROR;
    }
    int CheckBrother(Tree Now)//检测某个节点是否有兄弟,有则返回OK,否则返回ERROR
    {//可用
        Tree k;//临时指针
        if(Now->parent!=NULL)//不为祖先时,指向主孩子
         {
             k=Now->parent;//指向双亲
             k=k->children;//指向兄弟
         }
        else k=Now;
        if(k->brother==NULL)
            return ERROR;
        return OK;
    }
    */
    
    
    展开全文
  • 家族查询

    2014-12-22 10:54:34
    某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。 规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。如果x,y是亲戚,那么x的亲戚都是y...
    Time Limit: 1sec    Memory Limit:256MB
    Description

    某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。
    规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。如果x,y是亲戚,那么x的亲戚都是y的亲戚,y的亲戚也都是x的亲戚。(人数≤5000,询问亲戚关系次数≤5000)。

    Input

    第一行为数据组数T(T <= 20)

    对于每组数据,第一行有两个整数n、m(1 <= n, m <= 5000),表示有n个人,编号1~n,其中存在m个亲戚关系

    接下来m行,每行有两个整数u、v(u != v, 1 <= u, v <= n),表示u和v之间有亲戚关系

    然后是询问组数q(1 <= q <= 5000)

    接下来q行,每行有两个整数u、v(u != v, 1 <= u, v <= n),询问u和v之间是否有亲戚关系

     

    Output
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    
    using namespace std;
    
    int father[50002],a,b,m,n,p;
    
    
    //找到x的祖先 
    int find(int x){
    	if(father{x} != x){
    		father[x] = find(father[x]);
    		return father[x];
    	}
    } 
    
    
    int main(){
    	int q;
    	cin>>q;
    	while(q--){
    		
    		cin>>n>>m;
    		for(int i=1;i<=n;i++){
    			father[i] = i;
    		}
    		
    		for(int i=1;i<=m;i++){
    			cin>>a>>b;
    			a = find(a);
    			b = find(b);
    			father[a] = b;
    		}
    		
    		cin>>p;
    		for(int i=1;i<=p;i++){
    			cin>>a>>b;
    			a = find(a);
    			b = find(b);
    			if(a == b){
    				cout<<"Yes"<<endl; 
    			}
    			else cout<<"No"<<endl;
    		}
    		if(q != 0){
    			cout<<endl; 
    		}
    	}
    	return 0;
    }
    
    

    对于每组数据,输出q行,每行为"Yes"或"No",表示是否存在亲戚关系

    每组数据的输出用空行隔开



    展开全文
  • 在win32平台上用VC++6.0写的家族成员信息管理系统,可以统计家族的总体信息,添加新成员。期末作业你懂的
  • (1)普通用户、超级管理员不同角色,不同角色登录后的权限各不相同,普通用户可以进行查询;超级管理员有对所有成员增加、删除和修改的权限。 现在的初始超级管理员:admin 123456 初始普通用户:user555 123123 ...

    背景

    算法与数据结构实验内容,使用Java+JavaFX,花了两个星期独自完成。

    功能

    (1)普通用户、超级管理员不同角色,不同角色登录后的权限各不相同,普通用户可以进行查询;超级管理员有对所有成员增加、删除和修改的权限。
    现在的初始超级管理员:admin 123456
    初始普通用户:user555 123123
    (2)家谱中成员的信息中包含姓名、出生日期、婚否、地址、健在否、死亡日期(若其已死亡)等
    (3)数据以序列化存储于文本文件中。(xxx.data)
    每次正常关闭才可以保存修改成功
    (4)增删查改。可按照姓名查询,输出成员信息(包括其本人、父亲、孩子的信息、所在辈分);按照出生日期查询成员名单。
    (5)按出生日期对家谱中所有人排序。
    (6)打开家谱时,提示当天生日的健在成员。
    (7)输入任意两个姓名,能够查询这两个姓名之间的是否具有直系祖先后裔关系。
    (8)以图形方式显示家谱。

    数据结构说明

    在这里插入图片描述

    算法设计

    总体流程设计

    可视化界面跳转流程设计

    数据序列化和反序列化

    这是一个对于普遍对象的写入和读取部分。

    • 写:首先以文件输出位置为参数建立File类型对象,将其作为参数传入,建立文件输出流FileOutputStream对象,将其作为参数传入,建立对象输出流ObjectOutputStream对象,然后调用flush()方法把缓冲区的内容强制输出,最后将文件输出流close(),若不主动释放,它会持续占有资源。
    • 读:创建流的方式类似写的前三步,然后调用ObjectInputStream实例的readObject()方法读取,最后关闭流。值得注意的是,在调用读取方法时读取Object类型,需要强制转换为存储时的类型。
      在本程序中,每次进入登录界面读取可变数组类型的存储所有用户信息的数据,在登入后读取家谱树数据,在修改用户界面关闭时写入用户数据,在程序主界面正常关闭时进行两者的写入。

    增删查改移动查询直系

    首先要说明的是在实现中程序禁止了名字的重复,可重复部分在后面进行设计与分析。在对树结构有调整的操作中都需要再当前节点单独设置父母节点。在设置上父母是分离的两方,在需要绘制父母双方时可以只调整绘制程序实现。

    • 查找:这是一个递归的过程,传递的参数为Member和名字,结束条件为要找的名字等同于当前Member的名字,内部递归的调用为对当前成员的每个子嗣作为Member传入参数。在此方法外部封装:设置重写方法传入家谱树根进行全局的查找。同时,因为我们计算过用于生日排序的链表,也可以通过链表查找。
    • 插入(增加):每次先确认要插入的父母节点存在,将其设为要插入节点的父或母,将其加入插入节点的子女数组。
    • 删除:与上述类似,递归地调用自己,当名字符合时获得父母节点然后将自己从父母节点的子女数组删除。这个操作会删除所有下属的节点。同时,因为是一个无返回的方法,删除时会把所有此名的节点全部删除。
    • 修改不做赘述。
    • 移动:先查找符合的需要转移的节点和目标父母节点,都存在时将其删除,而后加入目标子女,最后将改动成员及其子树递归重新计算世代数。
      检查是否是直系亲属:两成员互相以对方为基点,在其子孙树下查找自己,如果有一方找到就是直系亲属。

    可以重复的树的设计(未实现):

    增加与删除全部同名没有问题,只是禁止了。

    • 查找:在tree下维护一个静态列表,记录每个名字的个数,每次加入删除时需要修改,同时被删除的子孙都需要修改个数,像维护每一代个数(已实现)一样做成方法每次刷新。
      查找与删除的定位:将在editcontroller中调用的方法定向为记录的界面右侧的member实例,每次给用户看一个,确定后对当前member删除,然后查找时做成查找与查找下一个,如果有同名可以查找下一个实例,根据list中的个数,通过在每个member类中新添加一个flag记录有没有被查过来实现,每次结束需要将flag归位,可以再次遍历来全部重置或者再开一个member类型数组记录已经查过的实例。
    • 查找与删除的另一个思路:在基础的树外部再建立二维都可变数组,每个名字为第一参数,内数组存同名个体们,然后都通过这个二维数组定位到记录。
      修改:通过查找下一个定位到个体后没有问题。
      移动:同上,定位两个个体让用户确定。
      #3 用户的增删查改
      与上述类似,且使用数组,更简单。仅允许管理员操作,不可删除当前账户,对密码限制必须大于六位,用户名是否重复判断。
      #3 家谱排序以及提示健在生日者
      在树的类中单独维护一个静态的链表来记录排序,在Member类中重写compareTo()方法,变成比较两个成员生日大小。已经有一个或多个的情况,比较第一个,比第一个小插入0位置;已经有多个的情况,比较前后相邻两个,大于前而小于后就插入其中;如果不满足前两个情况,在末尾插入。对树所有子女成员递归,排序所有人到这个链表。提示健在生日着只需要遍历,对每一个人调用getIsAlive()确认存活,然后确认生日是否一致,满足的打印提示。

    图形化

    每次首先清空画布,重新统计树每一层(代)的人数,记录在generationCount数组中,用以计算每一层节点之间的距离,统一计算,存储于xGap数组中。Count是在绘制时记录画的进度,每画一个节点在其层数已画计数加一。每次对所有子女先计算并画线,然后递归调用方法本身。
    另外,在本方法实现中也判断了当日生日且存活的成员并将其框画为蓝色。
    间隔具体计算式子:
    yGap = ((int)canvasHeight-2startY)/(generationCount.size()+1)-gridHeight;
    xGap[i] = (((int)canvasWidth-2
    startX))/(generationCount.get(i))-gridWidth;
    在这里插入图片描述

    初始化处理:

    初始化都是内置的单独方法,在图形化界面不可调用。树的初始化建立固定的根节点,用户信息的初始化建立固定用户名为admin,且密码为123456的管理员账户。

    实验数据制造

    我网上搜了个红楼梦关系图然后瞎编了一些个人信息:
    在这里插入图片描述

    实现效果:

    • 登录
      在这里插入图片描述

    • 用户修改界面
      在这里插入图片描述

    • 在注册界面成功注册和登录错误提示
      在这里插入图片描述

    • 初始化的主界面
      在这里插入图片描述

    • 主界面
      在这里插入图片描述

    • 修改界面以及添加操作(使用管理员账户登录)
      在这里插入图片描述

    • 全部添加完成,刷新后界面
      在这里插入图片描述

    • 增删查改例子的截图不多赘述,类似,在我的报告里有

    • 查询案例
      在这里插入图片描述

    • 查询两人是否有直属关系案例
      在这里插入图片描述

    仅供大家参考,学习,请勿原封不动使用

    源文件以及解释(我写的报告)

    CSDN下载:

    https://download.csdn.net/download/violet_ever_garden/12579899

    GitHub地址:

    https://github.com/FrankYJY/Genealogy-Management-System
    如果你觉得有帮助的话给颗Github星星吧
    如果你做到了改进,可以成为这个project的contributor

    b站解释视频:

    可以参考定位哪段代码对应什么功能,不详讲
    https://www.bilibili.com/video/BV1nz4y1X7rp/

    展开全文
  • 浅探 进程的家族关系

    2020-11-08 13:06:05
    进程的创建:编制一段程序,使用系统调用fork( )创建两个子进程,在该...(提示:运行过程中配拍摄进程的家族关系。) 代码: #include<stdio.h> int main(){ int p1,p2; while(( p1 = fork())== -1 ); if(p
  • 家族族谱系统 二叉树

    2013-06-24 10:26:06
    家族族谱实现,采用二叉树表示一个家谱关系。要求程序具有如下功能: (1) 文件操作功能:记录输入、记录输出,清除全部文件记录和将家谱记录存盘。 (2) 家谱操作功能:用括号表示法输出家谱二叉树,查找某人所有...
  • 家族族谱管理,数据结构代码
  • 第一章 引言 计算机等级考试查询系统是有其...我设计的这部分主要是查询系统,其中包含了超级管理员的查询、系管理员的查询和普通学生的查询。这就需要分别限定查询的权限问题。我个人认为是难点中的难点。因为这...
  • c语言数据结构期末大作业-家族族谱管理 要求设计实现具有下列功能的家谱管理系统: (1)输入文件以存放最初家谱中各成员的信息,成员的信息中均应包含以下内容: 姓名、出生日期、婚否、地址、健在否、死亡日期...
  • 本文设计了一个对数据输入输出储存查找的多功能软件本文需要保存家族的基本信息包括姓名及它们的关系但是由于家族信息很巨大而且关系很复杂所以采用二叉树来表示它们的关系并且具有保存文件的功能以便下次直接使用...
  • 如题,求大神protege软件上开发一个红楼梦家族的知识库系统,谢谢!!
  • 家谱管理系统.zip

    2019-07-11 18:41:10
    (B)家族关系存储:将各家庭成员之间的关系,存储在计算机中(可永久保存); (C)更新:家谱数据的更新(修改、删除、加入); (D)输出:将家谱以较友好的格式输出(显示); (E)查询:按基本信息查询成员...
  • 5.C语言家族扩展

    2011-11-24 15:03:20
    http://www.kerneltravel.net/newbie/gcc_man.html
  • 1.从文件读取家族信息并显示2.保存家族信息并存盘3....输入两人姓名,确定其关系9.给某成员添加孩子10.删除某成员(若其还有后代,则一并删除)11.修改某成员信息12.按出生日期对家谱中所有人排序13.退出系统
  • 课程设计家谱系统C

    2018-09-16 21:03:51
    C/C++开发的家谱系统,内含文档报告,课程设计类,不可做商业用
  • 随着人们对健康管理意识的提高及老龄化社会的到来,医院仅仅为患者提供疾病治疗的服务已不能满足大众对健康的需求,这就要医院将智能健康管理系统融入到医疗卫生服务体系中,对居民人体健康状况进行长时间监护管理,...
  • 一组由分布式文件系统和通用I/O的组件与接口(序列化, Java RPC, 持久化数据结构)。 Avro 一种支持高效、跨语言的RPC以及永久化存储数据的序列化系统。 MapReduce 分布式数据处理模型和执行环境,运行于...
  • 首先,对关联规则和Apriori算法的思路进行了全面的分析,之后创建以关联规则为基础的电力系统二次设备缺陷模型,通过模型思考二次设备缺陷的主要属性,包括二次设备类型、生产厂家及缺陷原因、部位等。最后,将自动...
  • 该应用程序包含在Docker容器中以简化依赖关系管理,因此主要依赖关系是Docker本身。 为您的操作系统 ,并且如果Docker安装随附的Docker 也请确保也它。 (后者不是硬性要求,但是使设置容器更加简单。) 将git ...
  • Perl :大多数操作系统默认安装Perl。 有关安装说明,请参见 。 Python :从下载可用的最新版本 BLAST :从以下地址下载blast可执行文件:ftp://ftp.ncbi.nlm.nih.gov/blast/executables/blast+/LATE

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 41,298
精华内容 16,519
关键字:

家族关系查询系统