数据结构课程设计家族关系查询系统Word格式.docx
《数据结构课程设计家族关系查询系统Word格式.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计家族关系查询系统Word格式.docx(29页珍藏版)》请在冰豆网上搜索。
#defineOK1
#defineERROR-1
#defineINFEASIBLE-1
typedef charDataType;
#defineMAXNUM20
typedef struct TriTNode/*树得三叉链表存储结构*/
{
ﻩDataType data[MAXNUM];
structTriTNode*parent;
/* 双亲*/
ﻩstruct TriTNode*lchild;
/*左孩子*/
structTriTNode*rchild;
/*右孩子*/
}TriTree;
typedefstructNode/*队列得结点结构*/
{ ﻩ
TriTree*info;
structNode *next;
}Node;
typedef struct/*链接队列类型定义*/
{ﻩ
structNode *front;
/*头指针*/
structNode*rear;
ﻩ /*尾指针*/
}LinkQueue;
DataTypefname[MAXNUM],family[50][MAXNUM];
/*全局变量*/
2、1、2 链队得基本操作
LinkQueue *LQueueCreateEmpty()/*建立一个空队列*/
{
LinkQueue*plqu=(LinkQueue*)malloc(sizeof(LinkQueue));
if(plqu!
=NULL)
plqu->
front=plqu->rear=NULL;
else
ﻩ{
ﻩﻩprintf("
内存不足!
\n"
);
ﻩreturnNULL;
}ﻩ
returnplqu;
}
intLQueueIsEmpty(LinkQueue*plqu)/* 判断链接表示队列就是否为空队列*/
{
return(plqu—>
front==NULL);
voidLQueueEnQueue(LinkQueue *plqu,TriTree *x)/* 进队列*/
{
Node*p=(Node*)malloc(sizeof(Node));
if(p==NULL)
printf("
内存分配失败!
\n”);
else
ﻩ{
p->
info=x;
p—>
next=NULL;
if(plqu-〉front==NULL)/*原来为空队*/
plqu-〉front=p;
else
plqu-〉rear-〉next=p;
plqu->rear=p;
}
int LQueueDeQueue(LinkQueue*plqu,TriTree*x)/*出队列*/
{
Node*p;
if(plqu->
front==NULL)
{
ﻩprintf("
队列空!
ﻩreturn ERROR;
else
{
p=plqu->
front;
ﻩx=p—>info;
plqu->
front=plqu-〉front->next;
free(p);
return OK;
}
}
TriTree*LQueueGetFront(LinkQueue*plqu)/*在非空队列中求队头元素*/
return(plqu—>front-〉info);
2、2建立家族关系
2、2、1建立家族关系并存入文件
基本思想:
首先输入家族关系得名称,以此名称为文件名,建立文本文件接下来按层次输入结点信息,输入一个在文件中写入一行同时将输入得信息保存
到二位字符数组family中.字符数组family就是全局变量,存储临时信息、 注意,输入时每个结点信息占一行,一个结点有多个兄弟,以“”作为兄弟结束标志,结点若无孩子,直接以“”代替。
依次输入各节点信息,以“#”作为结束标志。
最后使用函数CreateTriTree建立家族关系树、
lixian
liguoyuliguojunliguoqiang
liyongzhiliyongruiliyongming
liwendeliwenjia
TriTree*Create(DataTypefamilyname[MAXNUM])/*建立家族关系并存入文件*/
int i=0;
/* i控制family数组下标*/
DataType ch,str[MAXNUM];
/* ch存储输入得y或n,str存储输入得字符串*/
ﻩTriTree*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);
/*直接打开*/
returnt;
}
}
ﻩ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++;
/*family数组下标后移*/
ﻩﻩwhile(str[0]!
='#'
)
ﻩ{
ﻩﻩﻩprintf("
、");
/*以点提示符提示继续输入*/
ﻩgets(str);
ﻩfputs(str,fp);
/*写到文件中,每个信息占一行*/
fputc(’\n'
fp);
ﻩﻩstrcpy(family[i],str);
/*将成员信息存储到字符数组中*/
i++;
/*family数组下标后移*/
ﻩ}
ﻩfclose(fp);
/*关闭文件*/
ﻩt=TriTreeCreate();
/*根据family数组信息创建三叉树*/
ﻩprintf("家族关系已成功建立!
returnt;
/* 返回树*/
2、2、2建立家族关系树
采用指针数组作为指针,保存输入得结点地址。
队列得尾指针指向当前结点。
头指针指向当前结点得双亲结点。
输入得结点信息已存储在字符数组family中.
将信息复制到字符串数组“ch”中 ,如果"ch"
不就是“”,则建立一个新结点。
若新结点就是第一个结点,则它就是根结点,将其入队,指针tree指向这个根节点;
如果不就是根结点,则将当前结点链接到双亲结点上,即当前结点得双亲指针就就是队头元素,然后将当前结点入队列。
接着判断flag得值,如果flag=0,表示当前结点没有左孩子,那么当前结点就就是双亲得左孩子。
否则,当前结点就就是双亲得右孩子。
用指针root指向刚刚入队得结点。
继续复制数组family得下个元素。
如果“ch"
就是.则flag=0(因为“"
后面得第一个孩子为左孩子),同时判断“”就是否就是第一次出现,如果就是第一次,则令标志star=1;
如果不就是第一次出现.则出队列,root指向队头元素(实际上root总就是指向双亲结点)。
继续复制family得下一个元素。
知道遇到“#”结束.函数返回指针tree。
/*建立家族关系树*/
TriTree *TriTreeCreate()
TriTree*t,*x=NULL,*tree,*root=NULL;
LinkQueue*q=LQueueCreateEmpty();
/*建立一个空得队列,存储指向树得指针*/
ﻩinti=0,flag=0,start=0;
ﻩDataTypestr[MAXNUM];
/*存放family数组中信息*/
ﻩstrcpy(str,family[i]);
/*复制*/
i++;
/*family数组下标后移*/
ﻩwhile(str[0]!
=’#'
) /*没遇到结束标志继续循环*/
ﻩﻩwhile(str[0]!
='
’) /*没遇到兄弟输入结束标志继续*/
ﻩif(root==NULL) /*空树*/
ﻩﻩﻩ{
ﻩroot=(TriTree *)malloc(sizeof(TriTree));
/* 申请空间*/
ﻩﻩﻩstrcpy(root—>
data,str);
ﻩﻩﻩﻩroot-〉parent=NULL;
ﻩﻩﻩroot—〉lchild=NULL;
ﻩﻩroot->
rchild=NULL;
ﻩﻩﻩﻩLQueueEnQueue(q,root);
/*将root存入队列*/
ﻩtree=root;
ﻩ}
ﻩelse /*不为空树*/
ﻩﻩ{
ﻩt=(TriTree*)malloc(sizeof(TriTree));
/*申请空间*/
ﻩﻩstrcpy(t—>
data,str);
ﻩﻩt—〉lchild=NULL;
ﻩﻩﻩt—>rchild=NULL;
ﻩﻩﻩt-〉parent=LQueueGetFront(q);
/*当前结点得双亲为队头元素*/
ﻩﻩLQueueEnQueue(q,t);
/*入队*/
ﻩif(!
flag) /*flag为,当前结点没有左孩子*/
ﻩﻩroot—〉lchild=t;
ﻩelse/*flag为,当前结点已有左孩子*/
ﻩroot-〉rchild=t;
ﻩﻩﻩroot=t;
/*root指向新得结点t*/
}
ﻩﻩflag=1;
/* 标记当前结点已有左孩子*/
ﻩﻩstrcpy(str,family[i]);
ﻩﻩﻩi++;
if(start!
=0) /*标记不就是第一次出现“”*/
ﻩ{
ﻩﻩﻩLQueueDeQueue(q,x);
/*出队*/
ﻩﻩif(q->
front!
=NULL)
ﻩﻩﻩroot=LQueueGetFront(q);
/*root为队头元素*/
ﻩﻩ}
ﻩstart=1;
/*标记已出现过“”*/
flag=0;
/*“”后面得结点一定为左孩子*/
ﻩﻩstrcpy(str,family[i]);
ﻩi++;
ﻩreturntree;
/* 返回树*/
2、3打开一个家族关系
首先输入家族关系名,以家族名为文件名打开文件,如果家族关系不存在,返回空;
如果存在,文件打开,读取文件。
将文件得每行信息依次存储在数组family【】中。
/*打开一个家族关系*/
TriTree*Open(DataTypefamilyname[MAXNUM])
ﻩinti=0,j=0;
ﻩDataTypech;
FILE*fp;
ﻩTriTree*t;
strcpy(fname,familyname);
strcat(fname,"、txt”);
ﻩfp=fopen(fname,"
r");
/*以读取方式打开文件*/
ﻩif(fp==NULL) /* 文件不存在*/
ﻩprintf(”%s得家族关系不存在!
,familyname);
ﻩreturn NULL;
else
ﻩch=fgetc(fp);
/*按字符读取文件*/
ﻩﻩwhile(ch!
=EOF) /*读到文件尾结束*/
{
ﻩif(ch!
='\n'
) /* ch不为一个结点信息得结尾*/
ﻩ{
ﻩﻩﻩfamily[i][j]=ch;
/*将文件信息存储到family数组中*/
ﻩﻩﻩﻩj++;
ﻩelse
ﻩ{
ﻩﻩfamily[i][j]=’\0'
;
/*字符串结束标志*/
ﻩﻩi++;
/* family数组行下标后移*/
ﻩﻩj=0;
/* family数组列下标归零*/
ﻩ}
ﻩch=fgetc(fp);
/* 继续读取文件信息*/
ﻩ}
ﻩﻩfclose(fp);
/*关闭文件*/
ﻩﻩt=TriTreeCreate(family);
/*调用函数建立三叉链表*/
ﻩﻩprintf("
家族关系已成功打开!
\n”);
ﻩﻩreturnt;
ﻩ}
2、4在家族关系中查找一个成员就是否存在
用递归算法实现。
如果树空,返回NULL.如果根节点就就是要查找得成员,返回根节点;
否则,递归查找它得左右子树.
/*查找一个成员就是否存在*/
TriTree*Search(TriTree *t,DataTypestr[])
{ﻩ
TriTree*temp;
if(t==NULL) /* 如果树空则返回NULL*/
return NULL;
ﻩelseif(strcmp(t-〉data,str)==0)/* 如果找到返回该成员指针*/
ﻩreturnt;
else /*如果没找到遍历左右子树进行查找*/
ﻩtemp=Search(t—>lchild,str);
/*递归查找*/
if(temp) /*结点不空则查找*/
ﻩﻩreturn(Search(t->lchild,str));
ﻩﻩelse
ﻩreturn(Search(t—>
rchild,str));
2、5向家族中添加一个新成员
添加得新成员要根据其双亲确定其在家族中得位置.首先判断该双亲就是否在此家族关系中,若存在则查找其双亲,将新结点插入其双亲得最后一个孩子之后;
若没有孩子,则直接作为左孩子插入。
以写入得方式打开文件,如果成功打开,则更新family数组中得信息,并查找新成员得双亲所在位置与其对应得“"
个数,如果“”个数小于双亲位置,则添加“”实质相等,新成员不插入到最后“”之前。
最后将family数组中信息写入文件保存,关闭文件.
/*添加一个新成员*/
voidAppend(TriTree *t)
ﻩinti=0,j,parpos=1,curpos,num,end=0,count=-1;
ﻩDataType chi[MAXNUM],par[MAXNUM];
/*存储输入得孩子与其双亲结点*/
ﻩTriTree*tpar,*temp;
ﻩFILE*fp;
ﻩprintf(”请输入要添加得成员与其父亲,以回车分隔!
\n、");
gets(chi);
printf(”、”);
/*以点提示符提示继续输入*/
gets(par);
tpar=Search(t,par);
/*查找双亲结点就是否存在*/
if(!
tpar)
ﻩﻩprintf(”%s该成员不存在!
\n");
else /* 存在则添加其孩子*/
ﻩtemp=(TriTree*)malloc(sizeof(TriTree));
/*申请空间*/
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++;
/* parpos计数*/
ﻩi++;
/* family数组行下标后移*/
ﻩﻩﻩ}
i=0;
/*family数组行下标归*/
while(family[i][0]!
)
{
ﻩﻩif(family[i][0]==’’) /*查找“"
得个数,第一个不计*/
ﻩﻩcount++;
/*count累加个数*/
ﻩﻩif(count==parpos) /*说明此“"
与其前一个“"
之前为par得孩子*/
ﻩﻩﻩcurpos=i;
/* curpos计当前位置*/
ﻩﻩﻩi++;
/* family数组行下标后移*/
ﻩ}
ﻩﻩﻩif(count<
parpos) /*“”数小于parpos数*/
{
ﻩﻩﻩﻩnum=parpos—count;
/*添加“”个数为num */
ﻩﻩﻩ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;
/*end为时标记已添加*/
ﻩﻩfor(j=i;
j>
=curpos;
j——) /*当前位置到数组最后得全部信息后移一行*/
ﻩﻩstrcpy(family[j+1],family[j]);
ﻩﻩﻩstrcpy(family[curpos],chi);
/*将新结点存储到“”得前一行*/
ﻩif(end==1) /*若end为,则数组末尾下标后移num位*/
ﻩﻩﻩﻩi=i+num;
ﻩfor(j=0;
j〈=i+1;
j++) /*将数组所有信息写入文件*/
ﻩfputs(family[j],fp);
ﻩﻩﻩfputc('
\n'
,fp);
/*一个信息存一行*/
ﻩ}
ﻩfclose(fp);
/* 关闭文件*/
ﻩﻩprintf("添加新成员成功!
ﻩ}
ﻩelse
ﻩﻩprintf(”添加新成员失败!
\n");
2、6家族成员关系得相关查询
2、6、1查找一个家族得鼻祖
判断输入得姓名就是否在该家族中存在,如果存在,则返回该家族得根节点信息。
/