温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/1591651.html】到电脑端继续下载(重复下载【60天内】不扣币)。
1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。 2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。 3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。 4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。 5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。 6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:4009-655-100;投诉/维权电话:18658249818。
本文(数据结构课程设计(家族关系查询系统).doc)为本站上传会员【a199****6536】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。 温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。【 服务填表】
1、1 课程设计介绍 1、1课程设计项目简介 家谱就是一种以表谱形式,记载一个以血缘关系为主体得家族世系繁衍与重要人物事迹得特殊图书载体.家谱就是中国特有得文化遗产,就是中华民族得三大文献之一,属珍贵得人文资料,对于历史学,民俗学,人口学,社会学与经济学得深入研究,均有不可替代得重要功能。本项目对家谱管理进行简单得模拟,以实现查瞧祖先与子孙个人信息 、插入家族成员等功能。 1、2课设题目分析 本程序得实质就是完成对家谱成员信息得建立、查找、插入等功能。可以首先定义家族成员得数据结构,然后将每个功能写成一个函数来完成对数据得操作,最后完成主函数以验证各个函数功能并得出运行结果。
2、本程序包含以下几个模块 (1) 建立家族关系树。此模块将构建一个家族关系,对数据初始化,构造关系树并录入数据一遍后续程序使用。 (2) 添加新成员。此模块将添加一个新成员,实现对家族关系得修改。 (3) 家族关系得查询。此模块将实现对家族不同关系得查询 (4) 主程序模块。此模块实现整个程序得进入与进出,以及各种初始化处理。 1、3课程题目原理与数据结构 因为家族得成员之间存在一个对多个得层次结构关系,所以不能用线性表来表示与实现。家谱从形状上瞧像一颗倒长得树,所以用树结构来表示比较合适。树形结构就是一类非常重要得非线性数据结构,直观瞧来树就是以分支关系定义得层次结构. 因
3、此本课程设计可以采用得数据结构有树状结构与队列。树状结构采用三叉链表来实现,队列采用链式队列实现。 1、4功能分析说明图 家族关系查询系统 退出系统 打开一个家族关系 按关系查找各个家庭成员 建立一个家族关系 添加一个家庭成员 查找一个成员得兄弟 查找一个成员得祖先 查找成员得子孙后代 查找一个成员得孩子 查找成员得堂兄弟 查找成员祖先路径 查找成员就是第几代 查找一个成员双亲 2 分析与实现 2、1 基本数据结构与栈队得操作 2.1。1 结点基本数据结构与链队得定义 /*家族关系树实现*/ #include 〈string、h
4、〉 #include <malloc、h〉 #include<limits、h〉 #include<stdio、h> #include<stdlib、h> #include<io、h> #include5、表存储结构*/ { ﻩDataType data[MAXNUM]; ﻩstruct TriTNode *parent;/* 双亲*/ struct TriTNode *lchild;/* 左孩子*/ struct TriTNode *rchild;/* 右孩子*/ }TriTree; typedef struct Node/* 队列得结点结构*/ { TriTree *info; struct Node *next; }Node; typedef struct/* 链接队列类型定义*/ {ﻩ struct Node *fron6、t;ﻩ /* 头指针*/ struct Node *rear; /* 尾指针*/ }LinkQueue; DataType fname[MAXNUM],family[50][MAXNUM];/* 全局变量*/ 2.1.2 链队得基本操作 LinkQueue *LQueueCreateEmpty( )/* 建立一个空队列*/ { LinkQueue *plqu=(LinkQueue *)malloc(sizeof(LinkQueue)); if (plqu!=NULL) plqu—>front=plqu-〉rear=N7、ULL; else { printf(”内存不足!\n”); ﻩreturn NULL; } return plqu; } int LQueueIsEmpty(LinkQueue *plqu)/* 判断链接表示队列就是否为空队列*/ { return(plqu->front==NULL); } void LQueueEnQueue(LinkQueue *plqu,TriTree *x)/* 进队列*/ { Node *p=(Node *)malloc(sizeof(Node)); if(p==NULL) 8、 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)/* 出队列*/ { Nod9、e *p; if(plqu—>front==NULL) { ﻩ printf("队列空!\n”); 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-〉inf10、o); } 2、2建立家族关系 2.2.1 建立家族关系并存入文件 基本思想:首先输入家族关系得名称,以此名称为文件名,建立文本文件接下来按层次输入结点信息,输入一个在文件中写入一行同时将输入得信息保存 到二位字符数组family中。字符数组family就是全局变量,存储临时信息 、 注意,输入时每个结点信息占一行,一个结点有多个兄弟,以“”作为兄弟结束标志,结点若无孩子,直接以“"代替。依次输入各节点信息,以“#” 作为结束标志。最后使用函数CreateTriTree建立家族关系树、 lixian liguoyu li11、guojun liguoqiang liyongzhi liyongrui liyongming liwende liwenjia TriTree *Create(DataType familyname[MAXNUM])/* 建立家族关系并存入文件*/ { ﻩint i=0; 12、 /* 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 得家族关13、系已存在!重新建立请按“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("请按层次输入14、结点,每个结点信息占一行\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,15、fp); /* 写到文件中,每个信息占一行*/ ﻩ fputc('\n',fp); ﻩﻩ strcpy(family[i],str);/* 将成员信息存储到字符数组中*/ ﻩﻩ i++; /* family数组下标后移*/ ﻩﻩ} ﻩﻩfclose(fp); /* 关闭文件*/ t=TriTreeCreate(); /* 根据family数组信息创建三叉树*/ ﻩprintf("家族关系已成功建立!\n”); return t; /* 返回树*/ ﻩ} } 16、2。2。2建立家族关系树 基本思想:采用指针数组作为指针,保存输入得结点地址。队列得尾指针指向当前结点。头指针指向当前结点得双亲结点。输入得结点信息已存储在字符数组family中。 将信息复制到字符串数组“ch"中 ,如果”ch"不就是“”,则建立一个新结点。若新结点就是第一个结点,则它就是根结点,将其入队,指针tree指向这个根节点;如果不就是根结点,则将当前结点链接到双亲结点上,即当前结点得双亲指针就就是队头元素,然后将当前结点入队列.接着判断flag得值,如果flag=0,表示当前结点没有左孩子,那么当前结点就就是双亲得左孩子。否则,当前结点就就是双亲得右孩子.用指针root指向刚刚17、入队得结点.继续复制数组family得下个元素。如果“ch” 就是。则flag=0(因为“”后面得第一个孩子为左孩子),同时判断“”就是否就是第一次出现,如果就是第一次,则令标志star=1;如果不就是第一次出现.则出队列,root指向队头元素(实际上root总就是指向双亲结点)。继续复制family得下一个元素。知道遇到“#”结束。函数返回指针tree。 /* 建立家族关系树*/ TriTree *TriTreeCreate() { ﻩTriTree *t,*x=NULL,*tree,*root=NULL; LinkQueue *q=LQueueCreateEmpty()18、/* 建立一个空得队列,存储指向树得指针*/ int i=0,flag=0,start=0; DataType str[MAXNUM]; /* 存放family数组中信息*/ strcpy(str,family[i]); /* 复制*/ i++; /* family数组下标后移*/ while(str[0]!='#’) /* 没遇到结束标志继续循环*/ { ﻩ while(str[0]!=’’) /* 没遇到兄弟输入结束标志继续*/ ﻩﻩ{ ﻩﻩi19、f(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 20、 /* 不为空树*/ ﻩ { ﻩ ﻩﻩ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为,当前结点没有左孩21、子*/ ﻩﻩ 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); 22、 /* 出队*/ ﻩ ﻩif(q-〉front!=NULL) ﻩ ﻩroot=LQueueGetFront(q);/* root为队头元素*/ ﻩ } ﻩstart=1; /* 标记已出现过“"*/ ﻩﻩflag=0; /* “”后面得结点一定为左孩子*/ ﻩstrcpy(str,family[i]); i++; ﻩ} return tree; /* 返回树*/ } 2、3打开一个家族关系 首先输入家族关系名,以家族名为23、文件名打开文件,如果家族关系不存在,返回空;如果存在,文件打开,读取文件。将文件得每行信息依次存储在数组family【】中。 /* 打开一个家族关系*/ TriTree *Open(DataType familyname[MAXNUM]) { ﻩint i=0,j=0; ﻩDataType ch; FILE *fp; ﻩTriTree *t; strcpy(fname,familyname); /* 以家族名为文本文件名存储*/ strcat(fname,”、txt”); ﻩfp=fopen(fname,”r"); /* 以读取方式打开文件*/24、 ﻩif(fp==NULL) /* 文件不存在*/ { ﻩﻩprintf("%s 得家族关系不存在!\n”,familyname); ﻩﻩreturn NULL; } ﻩelse { ﻩ ch=fgetc(fp); /* 按字符读取文件*/ ﻩwhile(ch!=EOF) /* 读到文件尾结束*/ ﻩ{ ﻩﻩ if(ch!=’\n') /* ch不为一个结点信息得结尾*/ ﻩ { ﻩ ﻩfamily[i][j]=ch; /* 将文件信息存储到fa25、mily数组中*/ ﻩﻩj++; ﻩ } ﻩ ﻩelse ﻩﻩ { ﻩ ﻩfamily[i][j]='\0'; /* 字符串结束标志*/ ﻩ ﻩﻩi++; /* family数组行下标后移*/ ﻩﻩj=0; /* family数组列下标归零*/ ﻩ } ﻩch=fgetc(fp); /* 继续读取文件信息*/ ﻩ} ﻩﻩfclose(fp); /* 关闭文件*/ ﻩﻩt=TriTreeCreate(family); 26、 /* 调用函数建立三叉链表*/ printf("家族关系已成功打开!\n"); ﻩﻩreturn t; ﻩ} } 2、4在家族关系中查找一个成员就是否存在 用递归算法实现.如果树空,返回NULL。如果根节点就就是要查找得成员,返回根节点;否则,递归查找它得左右子树。 /* 查找一个成员就是否存在*/ TriTree *Search(TriTree *t,DataType str[]) { TriTree *temp; ﻩif(t==NULL) /* 如果树空则返回NULL */ ﻩreturn NULL; ﻩelse if(27、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)); ﻩ} } 2、5 向家族中添加一28、个新成员 基本思想:添加得新成员要根据其双亲确定其在家族中得位置。首先判断该双亲就是否在此家族关系中,若存在则查找其双亲,将新结点插入其双亲得最后一个孩子之后;若没有孩子,则直接作为左孩子插入。以写入得方式打开文件,如果成功打开,则更新family数组中得信息,并查找新成员得双亲所在位置与其对应得“"个数,如果“”个数小于双亲位置,则添加“"实质相等,新成员不插入到最后“”之前。最后将family数组中信息写入文件保存,关闭文件. /* 添加一个新成员*/ void Append(TriTree *t) { ﻩint i=0,j,parpos=1,curpos,num,end=0,c29、ount=—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 30、 /* 存在则添加其孩子*/ { ﻩﻩtemp=(TriTree *)malloc(sizeof(TriTree));/* 申请空间*/ temp->parent=tpar; ﻩ strcpy(temp—〉data,chi); ﻩﻩtemp->lchild=NULL; /* 新结点左右孩子置空*/ ﻩtemp—>rchild=NULL; ﻩﻩif(tpar->lchild)ﻩ /* 成员存在左孩子*/ ﻩ { ﻩ ﻩtpar=tpar—〉lchild; /* 遍历当前成员左孩子得右子树*/31、 ﻩﻩﻩwhile(tpar—〉rchild) ﻩ /* 当前结点右孩子存在*/ ﻩ ﻩtpar=tpar—>rchild; /* 继续遍历右孩子*/ ﻩﻩtpar—>rchild=temp; /* 将新结点添加到所有孩子之后*/ ﻩ } ﻩﻩelse /* 没有孩子则直接添加*/ ﻩ ﻩtpar->lchild=temp; ﻩfp=fopen(fname,”w"); /* 以写入方式打开文件*32、/ ﻩ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]!='#’) 33、 { ﻩ ﻩif(family[i][0]=='') /* 查找“"得个数,第一个不计*/ ﻩ ﻩcount++; /* count累加个数*/ ﻩ if(count==parpos) /* 说明此“”与其前一个“”之前为par得孩子*/ ﻩﻩﻩﻩ curpos=i; /* curpos计当前位置*/ ﻩ ﻩi++; /* family数组行下标后移*/ ﻩ } if(count〈parpos) /* “”数小于parp34、os数*/ ﻩ{ ﻩ 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 ﻩ35、 ﻩ{ ﻩﻩ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); ﻩ ﻩ fputc36、'\n’,fp); /* 一个信息存一行*/ ﻩﻩ } fclose(fp); /* 关闭文件*/ printf("添加新成员成功!\n"); ﻩ} else ﻩﻩ printf(”添加新成员失败!\n”); } } 2、6 家族成员关系得相关查询 2。6.1 查找一个家族得鼻祖 判断输入得姓名就是否在该家族中存在,如果存在,则返回该家族得根节点信息. /* 查找一个家族得祖先*/ void Ancesstor(TriTree *t) /* 返回树得根结点信37、息*/ { ﻩprintf("该家族得祖先为%s\n”,t->data); } 2.6。2 查找一个成员得所有祖先路径 查找一个成员得所有祖先路径,需要从它得双亲一直向上查找到根结点。 基本思想:对与结点t,先判断它就是否就是根结点(根节点得双亲就是NULL),如果就是根结点,直接输出它本身;如果不就是,查找它得双亲指针指向得结点,将双亲信息输出。继续查找,直到找到根结点. /* 查找一个成员得所有祖先*/ void AncesstorPath(TriTree *t) { if(t->parent==NULL) /* 若该成员为祖先,则直接输出*/ ﻩ prin38、tf(”%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"); 39、 } } 2.6.3 查找一个成员得双亲 基本思想:先判断结点t就是否就是根结点,过不就是根结点,直接输出该结点双亲指针得结点信息;若就是根结点,输出提示信息,结点无双亲。 /* 查找一个成员得双亲*/ void Parent(TriTree *t) { ﻩif(t-〉parent!=NULL) /* 若该成员为祖先,则无双亲*/ ﻩprintf("%s 得双亲为%s\n",t->data,t—〉parent-〉data); else ﻩﻩprintf("%s 无双亲!\n”,t-〉data); } 2.6.4 确定一个成员就是第几代 确定一个成员就是第几代40、只要知道从它本身到根结点包括得祖先个数就可。因而对于跟结点t,从它本身开始一直向上查找到根结点,查找得过程中用变量count(初值为1)计数,最后输出 count。 /* 确定一个成员就是第几代*/ void Generation(TriTree *t) { int count=1; /* 计数*/ DataType str[MAXNUM]; ﻩstrcpy(str,t—〉data); /* 存储当前信息*/ ﻩwhile(t—〉parent!=NULL)/* 查找其双亲*/ { ﻩﻩcount++; /* 累加计数*/ ﻩ t41、t->parent; } ﻩprintf("%s 就是第%d 代!\n”,str,count); } 2。6。5 查找一个成员得兄弟 一个成员得为其双亲除了该成员以外得所有孩子。 基本思想:对于结点t,先判断它就是否就是跟结点,若就是根结点,则无兄弟;若不就是根结点,则找到结点t得双亲。接着判断双亲得左孩子与左孩子得兄弟就是否都存在(若只有左孩子,左孩子就就是要查找得这个成员),如果都不存在,则无兄弟;如果都存在,对双亲得左孩子操作。若左孩子不就是要查找得这个成员,则将结点信息输出.接下来查找左孩子得右兄弟,判断当前结点就是否就是要查找得这个成员,若不就42、是,则将结点信息输出,继续查找当前结点得右兄弟,直到NULL为止. /* 查找一个成员得兄弟*/ void Brothers(TriTree *t,DataType str[]) /* 查找兄弟*/ { ﻩif(t->parent!=NULL) /* 若该结点就是祖先,则无兄弟*/ ﻩ{ ﻩt=t->parent; /* 该结点得兄弟即为其双亲除该成员以外得所有孩子*/ﻩ if(t->lchild&&t->lchild->rchild) /* 当前结点得左孩子及其右孩子都存在*/ ﻩ { ﻩﻩﻩpr43、intf("%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 ﻩ printf44、"%s 无兄弟!\n",str); } 2。6.6 查找一个成员得堂兄弟 一个成员得堂兄弟为其双亲得双亲结点得所有孩子得孩子(该成员除外)、 基本思想:如果结点t得双亲与双亲得双亲(爷爷)都存在,首先考虑爷爷得左孩子。如果爷爷得左孩子不就是结点t得双亲,那么爷爷还有其她孩子。现对爷爷得左孩子得左孩子访问,如果不就是结点t就输出。同样,对爷爷左孩子得左孩子得右孩子、右孩子得右孩子一直访问下去,直到无右孩子为止。如果爷爷还有其她孩子,那么就对爷爷得左孩子得右孩子、爷爷得左孩子得右孩子得右孩子—--—-—即对爷爷得其她孩子做相同得处理。 /* 查找一个成员得堂兄弟45、*/ void Consin(TriTree *t) { int flag=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)!46、0)/* 不就是同一结点*/ ﻩ ﻩ{ ﻩﻩﻩﻩif(t->lchild)ﻩ /* 当前结点存在左孩子*/ ﻩ{ ﻩﻩ ﻩtemp=t-〉lchild; ﻩ ﻩwhile(temp)ﻩﻩ /* 遍历当前结点左孩子得右子树*/ ﻩ ﻩ{ ﻩ if(strcmp(temp-〉data,ch-〉data)!=0) ﻩ ﻩﻩ { ﻩﻩﻩﻩﻩ if(!flag) /* 第一次输入时先输出下句*/ ﻩ ﻩ ﻩprintf("%s 得所有堂兄弟有:",ch->data); 47、ﻩ ﻩ printf("%s ",temp->data);/* 访问当前成员*/ ﻩ flag=1; ﻩ } ﻩﻩ ﻩﻩtemp=temp—>rchild; /* 继续遍历右孩子*/ ﻩﻩﻩ } ﻩ } ﻩﻩ} ﻩﻩﻩt=t->rchild; /* 继续遍历右孩子*/ ﻩﻩ} ﻩ printf(”\n"); ﻩ} ﻩif(!flag) /* 标志没有输出结点*/ printf(”%s 无堂兄弟!\n”,ch—>data); } 2.6。7 查找一个成员得所有孩48、子 一个成员得所有孩子包括左孩子与左孩子得右孩子、左孩子得右孩子得右孩子-—-—直到右孩子为空为止。 基本思想:首先判断结点t就是否有左孩子,如果没有,输出没有孩子;如果有左孩子,输出左孩子得信息,然后判断左孩子得右孩子就是否为空,若不为空(存在右孩子),输出左孩子得右孩子得信息,接着循环判断结点就是否有右孩子,有就输出,直到右孩子为空。 /* 查找一个成员得所有孩子*/ void Children(TriTree *t) /* 遍历左孩子*/ { if(t-〉lchild) /* 当前结点存在左孩子*/ { 49、 ﻩ 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(TriTree *t) 50、 { if(t) /* 二叉树存在*/ ﻩ{ ﻩ InOrder(t—>lchild); /* 中序遍历左子树*/ ﻩﻩprintf("%s ”,t-〉data);/* 访问成员*/ ﻩInOrder(t—>rchild); /* 中序遍历右子树*/ ﻩ} } 2.6.8 查找一个成员得子孙后代 一个成员得子孙后代就就是其左子树上得所有结点,所以对其左子树进行中序遍历即可。 /* 查找一个成员得子孙后代*/ void Descendants(TriTree *t) /* 遍历左孩子*/
5、表存储结构*/ { ﻩDataType data[MAXNUM]; ﻩstruct TriTNode *parent;/* 双亲*/ struct TriTNode *lchild;/* 左孩子*/ struct TriTNode *rchild;/* 右孩子*/ }TriTree; typedef struct Node/* 队列得结点结构*/ { TriTree *info; struct Node *next; }Node; typedef struct/* 链接队列类型定义*/ {ﻩ struct Node *fron
6、t;ﻩ /* 头指针*/ struct Node *rear; /* 尾指针*/ }LinkQueue; DataType fname[MAXNUM],family[50][MAXNUM];/* 全局变量*/ 2.1.2 链队得基本操作 LinkQueue *LQueueCreateEmpty( )/* 建立一个空队列*/ { LinkQueue *plqu=(LinkQueue *)malloc(sizeof(LinkQueue)); if (plqu!=NULL) plqu—>front=plqu-〉rear=N
7、ULL; else { printf(”内存不足!\n”); ﻩreturn NULL; } return plqu; } int LQueueIsEmpty(LinkQueue *plqu)/* 判断链接表示队列就是否为空队列*/ { return(plqu->front==NULL); } void LQueueEnQueue(LinkQueue *plqu,TriTree *x)/* 进队列*/ { Node *p=(Node *)malloc(sizeof(Node)); if(p==NULL)
8、 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)/* 出队列*/ { Nod
9、e *p; if(plqu—>front==NULL) { ﻩ printf("队列空!\n”); 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-〉inf
10、o); } 2、2建立家族关系 2.2.1 建立家族关系并存入文件 基本思想:首先输入家族关系得名称,以此名称为文件名,建立文本文件接下来按层次输入结点信息,输入一个在文件中写入一行同时将输入得信息保存 到二位字符数组family中。字符数组family就是全局变量,存储临时信息 、 注意,输入时每个结点信息占一行,一个结点有多个兄弟,以“”作为兄弟结束标志,结点若无孩子,直接以“"代替。依次输入各节点信息,以“#” 作为结束标志。最后使用函数CreateTriTree建立家族关系树、 lixian liguoyu li
11、guojun liguoqiang liyongzhi liyongrui liyongming liwende liwenjia TriTree *Create(DataType familyname[MAXNUM])/* 建立家族关系并存入文件*/ { ﻩint i=0;
12、 /* 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 得家族关
13、系已存在!重新建立请按“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("请按层次输入
14、结点,每个结点信息占一行\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,
15、fp); /* 写到文件中,每个信息占一行*/ ﻩ fputc('\n',fp); ﻩﻩ strcpy(family[i],str);/* 将成员信息存储到字符数组中*/ ﻩﻩ i++; /* family数组下标后移*/ ﻩﻩ} ﻩﻩfclose(fp); /* 关闭文件*/ t=TriTreeCreate(); /* 根据family数组信息创建三叉树*/ ﻩprintf("家族关系已成功建立!\n”); return t; /* 返回树*/ ﻩ} }
16、2。2。2建立家族关系树 基本思想:采用指针数组作为指针,保存输入得结点地址。队列得尾指针指向当前结点。头指针指向当前结点得双亲结点。输入得结点信息已存储在字符数组family中。 将信息复制到字符串数组“ch"中 ,如果”ch"不就是“”,则建立一个新结点。若新结点就是第一个结点,则它就是根结点,将其入队,指针tree指向这个根节点;如果不就是根结点,则将当前结点链接到双亲结点上,即当前结点得双亲指针就就是队头元素,然后将当前结点入队列.接着判断flag得值,如果flag=0,表示当前结点没有左孩子,那么当前结点就就是双亲得左孩子。否则,当前结点就就是双亲得右孩子.用指针root指向刚刚
17、入队得结点.继续复制数组family得下个元素。如果“ch” 就是。则flag=0(因为“”后面得第一个孩子为左孩子),同时判断“”就是否就是第一次出现,如果就是第一次,则令标志star=1;如果不就是第一次出现.则出队列,root指向队头元素(实际上root总就是指向双亲结点)。继续复制family得下一个元素。知道遇到“#”结束。函数返回指针tree。 /* 建立家族关系树*/ TriTree *TriTreeCreate() { ﻩTriTree *t,*x=NULL,*tree,*root=NULL; LinkQueue *q=LQueueCreateEmpty()
18、/* 建立一个空得队列,存储指向树得指针*/ int i=0,flag=0,start=0; DataType str[MAXNUM]; /* 存放family数组中信息*/ strcpy(str,family[i]); /* 复制*/ i++; /* family数组下标后移*/ while(str[0]!='#’) /* 没遇到结束标志继续循环*/ { ﻩ while(str[0]!=’’) /* 没遇到兄弟输入结束标志继续*/ ﻩﻩ{ ﻩﻩi
19、f(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
20、 /* 不为空树*/ ﻩ { ﻩ ﻩﻩ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为,当前结点没有左孩
21、子*/ ﻩﻩ 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);
22、 /* 出队*/ ﻩ ﻩif(q-〉front!=NULL) ﻩ ﻩroot=LQueueGetFront(q);/* root为队头元素*/ ﻩ } ﻩstart=1; /* 标记已出现过“"*/ ﻩﻩflag=0; /* “”后面得结点一定为左孩子*/ ﻩstrcpy(str,family[i]); i++; ﻩ} return tree; /* 返回树*/ } 2、3打开一个家族关系 首先输入家族关系名,以家族名为
23、文件名打开文件,如果家族关系不存在,返回空;如果存在,文件打开,读取文件。将文件得每行信息依次存储在数组family【】中。 /* 打开一个家族关系*/ TriTree *Open(DataType familyname[MAXNUM]) { ﻩint i=0,j=0; ﻩDataType ch; FILE *fp; ﻩTriTree *t; strcpy(fname,familyname); /* 以家族名为文本文件名存储*/ strcat(fname,”、txt”); ﻩfp=fopen(fname,”r"); /* 以读取方式打开文件*/
24、 ﻩif(fp==NULL) /* 文件不存在*/ { ﻩﻩprintf("%s 得家族关系不存在!\n”,familyname); ﻩﻩreturn NULL; } ﻩelse { ﻩ ch=fgetc(fp); /* 按字符读取文件*/ ﻩwhile(ch!=EOF) /* 读到文件尾结束*/ ﻩ{ ﻩﻩ if(ch!=’\n') /* ch不为一个结点信息得结尾*/ ﻩ { ﻩ ﻩfamily[i][j]=ch; /* 将文件信息存储到fa
25、mily数组中*/ ﻩﻩj++; ﻩ } ﻩ ﻩelse ﻩﻩ { ﻩ ﻩfamily[i][j]='\0'; /* 字符串结束标志*/ ﻩ ﻩﻩi++; /* family数组行下标后移*/ ﻩﻩj=0; /* family数组列下标归零*/ ﻩ } ﻩch=fgetc(fp); /* 继续读取文件信息*/ ﻩ} ﻩﻩfclose(fp); /* 关闭文件*/ ﻩﻩt=TriTreeCreate(family);
26、 /* 调用函数建立三叉链表*/ printf("家族关系已成功打开!\n"); ﻩﻩreturn t; ﻩ} } 2、4在家族关系中查找一个成员就是否存在 用递归算法实现.如果树空,返回NULL。如果根节点就就是要查找得成员,返回根节点;否则,递归查找它得左右子树。 /* 查找一个成员就是否存在*/ TriTree *Search(TriTree *t,DataType str[]) { TriTree *temp; ﻩif(t==NULL) /* 如果树空则返回NULL */ ﻩreturn NULL; ﻩelse if(
27、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)); ﻩ} } 2、5 向家族中添加一
28、个新成员 基本思想:添加得新成员要根据其双亲确定其在家族中得位置。首先判断该双亲就是否在此家族关系中,若存在则查找其双亲,将新结点插入其双亲得最后一个孩子之后;若没有孩子,则直接作为左孩子插入。以写入得方式打开文件,如果成功打开,则更新family数组中得信息,并查找新成员得双亲所在位置与其对应得“"个数,如果“”个数小于双亲位置,则添加“"实质相等,新成员不插入到最后“”之前。最后将family数组中信息写入文件保存,关闭文件. /* 添加一个新成员*/ void Append(TriTree *t) { ﻩint i=0,j,parpos=1,curpos,num,end=0,c
29、ount=—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
30、 /* 存在则添加其孩子*/ { ﻩﻩtemp=(TriTree *)malloc(sizeof(TriTree));/* 申请空间*/ temp->parent=tpar; ﻩ strcpy(temp—〉data,chi); ﻩﻩtemp->lchild=NULL; /* 新结点左右孩子置空*/ ﻩtemp—>rchild=NULL; ﻩﻩif(tpar->lchild)ﻩ /* 成员存在左孩子*/ ﻩ { ﻩ ﻩtpar=tpar—〉lchild; /* 遍历当前成员左孩子得右子树*/
31、 ﻩﻩﻩwhile(tpar—〉rchild) ﻩ /* 当前结点右孩子存在*/ ﻩ ﻩtpar=tpar—>rchild; /* 继续遍历右孩子*/ ﻩﻩtpar—>rchild=temp; /* 将新结点添加到所有孩子之后*/ ﻩ } ﻩﻩelse /* 没有孩子则直接添加*/ ﻩ ﻩtpar->lchild=temp; ﻩfp=fopen(fname,”w"); /* 以写入方式打开文件*
32、/ ﻩ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]!='#’)
33、 { ﻩ ﻩif(family[i][0]=='') /* 查找“"得个数,第一个不计*/ ﻩ ﻩcount++; /* count累加个数*/ ﻩ if(count==parpos) /* 说明此“”与其前一个“”之前为par得孩子*/ ﻩﻩﻩﻩ curpos=i; /* curpos计当前位置*/ ﻩ ﻩi++; /* family数组行下标后移*/ ﻩ } if(count〈parpos) /* “”数小于parp
34、os数*/ ﻩ{ ﻩ 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 ﻩ
35、 ﻩ{ ﻩﻩ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
36、'\n’,fp); /* 一个信息存一行*/ ﻩﻩ } fclose(fp); /* 关闭文件*/ printf("添加新成员成功!\n"); ﻩ} else ﻩﻩ printf(”添加新成员失败!\n”); } } 2、6 家族成员关系得相关查询 2。6.1 查找一个家族得鼻祖 判断输入得姓名就是否在该家族中存在,如果存在,则返回该家族得根节点信息. /* 查找一个家族得祖先*/ void Ancesstor(TriTree *t) /* 返回树得根结点信
37、息*/ { ﻩprintf("该家族得祖先为%s\n”,t->data); } 2.6。2 查找一个成员得所有祖先路径 查找一个成员得所有祖先路径,需要从它得双亲一直向上查找到根结点。 基本思想:对与结点t,先判断它就是否就是根结点(根节点得双亲就是NULL),如果就是根结点,直接输出它本身;如果不就是,查找它得双亲指针指向得结点,将双亲信息输出。继续查找,直到找到根结点. /* 查找一个成员得所有祖先*/ void AncesstorPath(TriTree *t) { if(t->parent==NULL) /* 若该成员为祖先,则直接输出*/ ﻩ prin
38、tf(”%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");
39、 } } 2.6.3 查找一个成员得双亲 基本思想:先判断结点t就是否就是根结点,过不就是根结点,直接输出该结点双亲指针得结点信息;若就是根结点,输出提示信息,结点无双亲。 /* 查找一个成员得双亲*/ void Parent(TriTree *t) { ﻩif(t-〉parent!=NULL) /* 若该成员为祖先,则无双亲*/ ﻩprintf("%s 得双亲为%s\n",t->data,t—〉parent-〉data); else ﻩﻩprintf("%s 无双亲!\n”,t-〉data); } 2.6.4 确定一个成员就是第几代 确定一个成员就是第几代
40、只要知道从它本身到根结点包括得祖先个数就可。因而对于跟结点t,从它本身开始一直向上查找到根结点,查找得过程中用变量count(初值为1)计数,最后输出 count。 /* 确定一个成员就是第几代*/ void Generation(TriTree *t) { int count=1; /* 计数*/ DataType str[MAXNUM]; ﻩstrcpy(str,t—〉data); /* 存储当前信息*/ ﻩwhile(t—〉parent!=NULL)/* 查找其双亲*/ { ﻩﻩcount++; /* 累加计数*/ ﻩ t
41、t->parent; } ﻩprintf("%s 就是第%d 代!\n”,str,count); } 2。6。5 查找一个成员得兄弟 一个成员得为其双亲除了该成员以外得所有孩子。 基本思想:对于结点t,先判断它就是否就是跟结点,若就是根结点,则无兄弟;若不就是根结点,则找到结点t得双亲。接着判断双亲得左孩子与左孩子得兄弟就是否都存在(若只有左孩子,左孩子就就是要查找得这个成员),如果都不存在,则无兄弟;如果都存在,对双亲得左孩子操作。若左孩子不就是要查找得这个成员,则将结点信息输出.接下来查找左孩子得右兄弟,判断当前结点就是否就是要查找得这个成员,若不就
42、是,则将结点信息输出,继续查找当前结点得右兄弟,直到NULL为止. /* 查找一个成员得兄弟*/ void Brothers(TriTree *t,DataType str[]) /* 查找兄弟*/ { ﻩif(t->parent!=NULL) /* 若该结点就是祖先,则无兄弟*/ ﻩ{ ﻩt=t->parent; /* 该结点得兄弟即为其双亲除该成员以外得所有孩子*/ﻩ if(t->lchild&&t->lchild->rchild) /* 当前结点得左孩子及其右孩子都存在*/ ﻩ { ﻩﻩﻩpr
43、intf("%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
44、"%s 无兄弟!\n",str); } 2。6.6 查找一个成员得堂兄弟 一个成员得堂兄弟为其双亲得双亲结点得所有孩子得孩子(该成员除外)、 基本思想:如果结点t得双亲与双亲得双亲(爷爷)都存在,首先考虑爷爷得左孩子。如果爷爷得左孩子不就是结点t得双亲,那么爷爷还有其她孩子。现对爷爷得左孩子得左孩子访问,如果不就是结点t就输出。同样,对爷爷左孩子得左孩子得右孩子、右孩子得右孩子一直访问下去,直到无右孩子为止。如果爷爷还有其她孩子,那么就对爷爷得左孩子得右孩子、爷爷得左孩子得右孩子得右孩子—--—-—即对爷爷得其她孩子做相同得处理。 /* 查找一个成员得堂兄弟
45、*/ void Consin(TriTree *t) { int flag=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)!
46、0)/* 不就是同一结点*/ ﻩ ﻩ{ ﻩﻩﻩﻩif(t->lchild)ﻩ /* 当前结点存在左孩子*/ ﻩ{ ﻩﻩ ﻩtemp=t-〉lchild; ﻩ ﻩwhile(temp)ﻩﻩ /* 遍历当前结点左孩子得右子树*/ ﻩ ﻩ{ ﻩ if(strcmp(temp-〉data,ch-〉data)!=0) ﻩ ﻩﻩ { ﻩﻩﻩﻩﻩ if(!flag) /* 第一次输入时先输出下句*/ ﻩ ﻩ ﻩprintf("%s 得所有堂兄弟有:",ch->data);
47、ﻩ ﻩ printf("%s ",temp->data);/* 访问当前成员*/ ﻩ flag=1; ﻩ } ﻩﻩ ﻩﻩtemp=temp—>rchild; /* 继续遍历右孩子*/ ﻩﻩﻩ } ﻩ } ﻩﻩ} ﻩﻩﻩt=t->rchild; /* 继续遍历右孩子*/ ﻩﻩ} ﻩ printf(”\n"); ﻩ} ﻩif(!flag) /* 标志没有输出结点*/ printf(”%s 无堂兄弟!\n”,ch—>data); } 2.6。7 查找一个成员得所有孩
48、子 一个成员得所有孩子包括左孩子与左孩子得右孩子、左孩子得右孩子得右孩子-—-—直到右孩子为空为止。 基本思想:首先判断结点t就是否有左孩子,如果没有,输出没有孩子;如果有左孩子,输出左孩子得信息,然后判断左孩子得右孩子就是否为空,若不为空(存在右孩子),输出左孩子得右孩子得信息,接着循环判断结点就是否有右孩子,有就输出,直到右孩子为空。 /* 查找一个成员得所有孩子*/ void Children(TriTree *t) /* 遍历左孩子*/ { if(t-〉lchild) /* 当前结点存在左孩子*/ {
49、 ﻩ 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(TriTree *t)
50、 { if(t) /* 二叉树存在*/ ﻩ{ ﻩ InOrder(t—>lchild); /* 中序遍历左子树*/ ﻩﻩprintf("%s ”,t-〉data);/* 访问成员*/ ﻩInOrder(t—>rchild); /* 中序遍历右子树*/ ﻩ} } 2.6.8 查找一个成员得子孙后代 一个成员得子孙后代就就是其左子树上得所有结点,所以对其左子树进行中序遍历即可。 /* 查找一个成员得子孙后代*/ void Descendants(TriTree *t) /* 遍历左孩子*/
关于我们 便捷服务 自信AI AI导航 抽奖活动
©2010-2025 宁波自信网络信息技术有限公司 版权所有
客服电话:4009-655-100 投诉/维权电话:18658249818
浙公网安备33021202000488号
浙ICP备2021020529号-1 | 浙B2-20240490
关注我们 :