家族关系查询系统

家族关系查询系统

1.问题描述

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

2.基本要求

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

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

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

3.扩展功能

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

 

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

 

#include 
#include
#include 
#include
#include
#include
#include
#include
#include
#include
#include
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<<"请输入家族名氏"<>str;
            temp=Search(tree,str);
            if(!temp)             // 若不存在则返回
            {
                printf("该成员不存在!\n");
                continue;
            }
            AncestorPath(temp);
            break;
        case 6:
            cout<<"请输入成员名氏"<>str;
            temp=Search(tree,str);
            if(!temp)             // 若不存在则返回
            {
                printf("该成员不存在!\n");
                continue;
            }
            Generation(temp);
            break;
        case 7:
            cout<<"请输入成员名氏"<>str;
            temp=Search(tree,str);
            if(!temp)             // 若不存在则返回
            {
                printf("该成员不存在!\n");
                continue;
            }
            Parent(temp);
            break;
        case 8:
            cout<<"请输入成员名氏"<>str;
            temp=Search(tree,str);
            if(!temp)             // 若不存在则返回
            {
                printf("该成员不存在!\n");
                continue;
            }
            Brothers(temp,str);
            break;
        case 9:
            cout<<"请输入成员名氏"<>str;
            temp=Search(tree,str);
            if(!temp)             // 若不存在则返回
            {
                printf("该成员不存在!\n");
                continue;
            }
            Consin(temp);
            break;
        case 10:
            cout<<"请输入成员名氏"<>str;
            temp=Search(tree,str);
            if(!temp)             // 若不存在则返回
            {
                printf("该成员不存在!\n");
                continue;
            }
            Children(temp);
            break;
        case 11:
            cout<<"请输入成员名氏"<>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;
    queueq;
    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=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<<"添加新成员成功!"<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);
}

 

你可能感兴趣的:(数据结构)