家族程序.docx
- 文档编号:24456218
- 上传时间:2023-05-27
- 格式:DOCX
- 页数:23
- 大小:20.13KB
家族程序.docx
《家族程序.docx》由会员分享,可在线阅读,更多相关《家族程序.docx(23页珍藏版)》请在冰豆网上搜索。
家族程序
#include
#include
#include
#include
typedefcharDataType;
#defineMAXNUM20
#defineERROR0
#defineOK1
typedefstructTriNode
{
DataTypedata[MAXNUM];
structTriNode*parent;//双亲
structTriNode*lchild;//左孩子
structTriNode*rchild;//右孩子
}TriTree;
typedefstructNode//队列的结点结构
{
TriTree*info;
structNode*next;
}Node;
typedefstruct//连接队列类型定义
{
structNode*front;//头指针
structNode*rear;//尾指针
}LinkQueue;
DataTypefname[MAXNUM],family[50][MAXNUM];//全局变量
TriTree*Open(DataTypefamilyname[MAXNUM]);
TriTree*TriTreeCreate();
TriTree*Search(TriTree*t,DataTypestr[]);
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;
}
}
intLQueueDeQueue(LinkQueue*plqu,TriTree*x)//出队列
{
Node*p;
if(plqu->front==NULL)
{
printf("队列空!
\n");
returnERROR;
}
else
{
p=plqu->front;
x=p->info;
plqu->front=plqu->front->next;
free(p);
returnOK;
}
}
TriTree*LQueueFront(LinkQueue*plqu)//在空队列中求对头元素
{
return(plqu->front->info);
}
TriTree*Create(DataTypefamilyname[MAXNUM])//建立家族关系并存入文件
{
inti=0;//i控制family数组下标
DataTypech,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("家族关系已成功建立!
\n");
//返回树
}
returnt;
}
TriTree*TriTreeCreate()
{
TriTree*t,*x=NULL,*root=NULL,*tree;
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=LQueueFront(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=LQueueFront(q);//root为对头元素
}
start=1;//标记已出现过"@"
flag=0;//"@"后面的节点一定为左孩子
strcpy(str,family[i]);
i++;
}
returntree;//返回树
}
TriTree*Open(DataTypefamilyname[MAXNUM])
{
inti=0,j=0;
TriTree*t;
DataTypech;
FILE*fp;
strcpy(fname,familyname);//以家族名义为文本文件名储存
strcat(fname,".txt");//将字符.txt连接到fname中去
fp=fopen(fname,"r");//以读取方式打开文件
if(fp==NULL)//文件不存在
{
printf("%s的家族关系不存在!
\n",familyname);
returnNULL;
}
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();//调用函数建立三叉链表
printf("家族关系已打开成功!
\n");
returnt;
}
}
voidAppend(TriTree*t)
{
inti=0,j,parpos=1,curpos,num,end=0,count=-1;
DataTypechi[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 { 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为时标记已添加 } else { 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); fputs("\n",fp);//一个信息存一行 } fclose(fp);//关闭文件 printf("添加新成员成功! \n"); } else printf("添加新成员失败! \n"); } } voidAncesstorPath(TriTree*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->data,t->data);//访问当前成员的双亲 t=t->parent;//继续循环查找 } printf("\n"); } } voidAncesstor(TriTree*t)//返回树的根节点信息 { printf("该家族的祖先为%s\n",t->data); } voidParent(TriTree*t) { if(t->parent! =NULL)//若该成员为祖先,则无双亲 printf("%s的双亲为%s\n",t->data,t->parent->data); else printf("%s无双亲! \n",t->data); } voidBrothers(TriTree*t,DataTypestr[]) { if(t->parent! =NULL)//若该节点是祖先,则无兄弟 { t=t->parent; if(t->lchild&&t->lchild->rchild)//当前节点的左孩子及右孩子都存在 { printf("%s的所有兄弟有: \n",str); t=t->lchild;//遍历当前成员左孩子的右子树 while(t) { if(strcmp(t->data,str)! =0)//遍历右子树,选择输出 printf("%s\n",t->data);//访问当前节点 t=t->rchild; } printf("\n"); } else printf("%s无兄弟! \n",str); } else printf("%s无兄弟! \n",str); } voidConsin(TriTree*t) { intflag=0; TriTree*ch=t; TriTree*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); } voidChildren(TriTree*t) { if(t->lchild)//当前节点存在左孩子 { printf("%s的所有孩子有: \n",t->data); t=t->lchild;//遍历当前成员左孩子的右子树 while(t)//不空 { printf("%s\n",t->data);//访问当前成员 t=t->rchild; } printf("\n"); } else printf("%s无孩子! \n",t->data); } voidInOrder(TriTree*t) //196-197 { if(t)//二叉树存在 { InOrder(t->rchild);//中序遍历左子树 printf("%s",t->data);//访问成员 InOrder(t->rchild);//中序遍历右子树 } } voidDescendants(TriTree*t)//查找一个成员的子孙后代 { if(t->lchild)//当前节点存在左孩子 { printf("%s的所有子孙后代有: ",t->data); InOrder(t->lchild);//中序遍历当前结点的左右子树 printf("\n"); } else printf("%s无后代! \n",t->data); } voidGeneration(TriTree*t) { intcount=1;//计数 DataTypestr[MAXNUM]; strcpy(str,t->data);//存储当前信息 while(t->parent! =NULL)//查找其双亲 { count++;//累加计数 t=t->parent; } printf("%s是第%d代\n",str,count); } TriTree*Search(TriTree*t,DataTypestr[]) { TriTree*temp; if(t==NULL)//如果树空,则返回NULL returnNULL; 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)); } } intmain(intargc,char*argv[]) { DataTypestr[MAXNUM]="\0",input[40]; inti,j,flag,start=0,pos,tag1,tag2; TriTree*temp,*tree=NULL; while (1) { printf("\t欢迎使用家族关系查询系统! \n"); printf("\t请输入与之匹配的函数和参数,如parent(c)\n"); printf("\t1.新建一个家庭关系: Create(familyname)参数为字符串\n"); printf("\t2.打开一个家庭关系: Open(familyname)参数为字符串\n"); printf("\t3.添加新成员的信息: Append()无参数\n"); printf("\t4.查找一个成员的祖先: Ancesstor(name)参数为字符串\n"); printf("\t5.查找一个成员的祖先的路径: Ancesstorpath(name)参数为字符串\n"); printf("\t6.确定一个成员是第几代: Generation(name)参数为字符串\n"); printf("\t7.查找一个成员的双亲: Parent(name)参数为字符串\n"); printf("\t8.查找一个成员的兄弟: Brothers(name)参数为字符串\n"); printf("\t9.查找一个成员的堂兄弟: Consin(name)参数为字符串\n"); printf("\t10.查找一个成员的孩子: Children(name)参数为字符
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 家族 程序