资源描述
1 课程设计介绍
1、1课程设计项目简介
家谱就是一种以表谱形式,记载一个以血缘关系为主体得家族世系繁衍与重要人物事迹得特殊图书载体.家谱就是中国特有得文化遗产,就是中华民族得三大文献之一,属珍贵得人文资料,对于历史学,民俗学,人口学,社会学与经济学得深入研究,均有不可替代得重要功能。本项目对家谱管理进行简单得模拟,以实现查瞧祖先与子孙个人信息 、插入家族成员等功能。
1、2课设题目分析
本程序得实质就是完成对家谱成员信息得建立、查找、插入等功能。可以首先定义家族成员得数据结构,然后将每个功能写成一个函数来完成对数据得操作,最后完成主函数以验证各个函数功能并得出运行结果。
本程序包含以下几个模块
(1) 建立家族关系树。此模块将构建一个家族关系,对数据初始化,构造关系树并录入数据一遍后续程序使用。
(2) 添加新成员。此模块将添加一个新成员,实现对家族关系得修改。
(3) 家族关系得查询。此模块将实现对家族不同关系得查询
(4) 主程序模块。此模块实现整个程序得进入与进出,以及各种初始化处理。
1、3课程题目原理与数据结构
因为家族得成员之间存在一个对多个得层次结构关系,所以不能用线性表来表示与实现。家谱从形状上瞧像一颗倒长得树,所以用树结构来表示比较合适。树形结构就是一类非常重要得非线性数据结构,直观瞧来树就是以分支关系定义得层次结构.
因此本课程设计可以采用得数据结构有树状结构与队列。树状结构采用三叉链表来实现,队列采用链式队列实现。
1、4功能分析说明图
家族关系查询系统
退出系统
打开一个家族关系
按关系查找各个家庭成员
建立一个家族关系
添加一个家庭成员
查找一个成员得兄弟
查找一个成员得祖先
查找成员得子孙后代
查找一个成员得孩子
查找成员得堂兄弟
查找成员祖先路径
查找成员就是第几代
查找一个成员双亲
2 分析与实现
2、1 基本数据结构与栈队得操作
2.1。1 结点基本数据结构与链队得定义
/*家族关系树实现*/
#include 〈string、h〉
#include <malloc、h〉
#include<limits、h〉
#include<stdio、h>
#include<stdlib、h>
#include<io、h>
#include<math、h>
#include<process、h〉
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR -1
#define INFEASIBLE -1
typedef char DataType;
#define MAXNUM 20
typedef struct TriTNode/* 树得三叉链表存储结构*/
{
ﻩ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 *front;ﻩ /* 头指针*/
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=NULL;
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)
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("队列空!\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-〉info);
}
2、2建立家族关系
2.2.1 建立家族关系并存入文件
基本思想:首先输入家族关系得名称,以此名称为文件名,建立文本文件接下来按层次输入结点信息,输入一个在文件中写入一行同时将输入得信息保存
到二位字符数组family中。字符数组family就是全局变量,存储临时信息 、 注意,输入时每个结点信息占一行,一个结点有多个兄弟,以“”作为兄弟结束标志,结点若无孩子,直接以“"代替。依次输入各节点信息,以“#” 作为结束标志。最后使用函数CreateTriTree建立家族关系树、
lixian
liguoyu liguojun liguoqiang
liyongzhi liyongrui liyongming
liwende liwenjia
TriTree *Create(DataType familyname[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);/* 直接打开*/
ﻩ 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++; /* 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”);
return t; /* 返回树*/
ﻩ}
}
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();/* 建立一个空得队列,存储指向树得指针*/
int i=0,flag=0,start=0;
DataType str[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++;
ﻩ}
return tree; /* 返回树*/
}
2、3打开一个家族关系
首先输入家族关系名,以家族名为文件名打开文件,如果家族关系不存在,返回空;如果存在,文件打开,读取文件。将文件得每行信息依次存储在数组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"); /* 以读取方式打开文件*/
ﻩif(fp==NULL) /* 文件不存在*/
{
ﻩﻩprintf("%s 得家族关系不存在!\n”,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");
ﻩﻩreturn t;
ﻩ}
}
2、4在家族关系中查找一个成员就是否存在
用递归算法实现.如果树空,返回NULL。如果根节点就就是要查找得成员,返回根节点;否则,递归查找它得左右子树。
/* 查找一个成员就是否存在*/
TriTree *Search(TriTree *t,DataType str[])
{
TriTree *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));
ﻩ}
}
2、5 向家族中添加一个新成员
基本思想:添加得新成员要根据其双亲确定其在家族中得位置。首先判断该双亲就是否在此家族关系中,若存在则查找其双亲,将新结点插入其双亲得最后一个孩子之后;若没有孩子,则直接作为左孩子插入。以写入得方式打开文件,如果成功打开,则更新family数组中得信息,并查找新成员得双亲所在位置与其对应得“"个数,如果“”个数小于双亲位置,则添加“"实质相等,新成员不插入到最后“”之前。最后将family数组中信息写入文件保存,关闭文件.
/* 添加一个新成员*/
void Append(TriTree *t)
{
ﻩint i=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为时标记已添加*/
ﻩ}
ﻩﻩ 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);
ﻩ ﻩ fputc('\n’,fp); /* 一个信息存一行*/
ﻩﻩ }
fclose(fp); /* 关闭文件*/
printf("添加新成员成功!\n");
ﻩ}
else
ﻩﻩ printf(”添加新成员失败!\n”);
}
}
2、6 家族成员关系得相关查询
2。6.1 查找一个家族得鼻祖
判断输入得姓名就是否在该家族中存在,如果存在,则返回该家族得根节点信息.
/* 查找一个家族得祖先*/
void Ancesstor(TriTree *t) /* 返回树得根结点信息*/
{
ﻩprintf("该家族得祖先为%s\n”,t->data);
}
2.6。2 查找一个成员得所有祖先路径
查找一个成员得所有祖先路径,需要从它得双亲一直向上查找到根结点。
基本思想:对与结点t,先判断它就是否就是根结点(根节点得双亲就是NULL),如果就是根结点,直接输出它本身;如果不就是,查找它得双亲指针指向得结点,将双亲信息输出。继续查找,直到找到根结点.
/* 查找一个成员得所有祖先*/
void AncesstorPath(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-〉parent-〉data); /* 访问当前成员得双亲*/
ﻩﻩt=t—〉parent; /* 继续循环查找*/
ﻩ }
ﻩﻩprintf(”\n");
}
}
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 确定一个成员就是第几代
确定一个成员就是第几代,只要知道从它本身到根结点包括得祖先个数就可。因而对于跟结点t,从它本身开始一直向上查找到根结点,查找得过程中用变量count(初值为1)计数,最后输出 count。
/* 确定一个成员就是第几代*/
void Generation(TriTree *t)
{
int count=1; /* 计数*/
DataType str[MAXNUM];
ﻩstrcpy(str,t—〉data); /* 存储当前信息*/
ﻩwhile(t—〉parent!=NULL)/* 查找其双亲*/
{
ﻩﻩcount++; /* 累加计数*/
ﻩ t=t->parent;
}
ﻩprintf("%s 就是第%d 代!\n”,str,count);
}
2。6。5 查找一个成员得兄弟
一个成员得为其双亲除了该成员以外得所有孩子。
基本思想:对于结点t,先判断它就是否就是跟结点,若就是根结点,则无兄弟;若不就是根结点,则找到结点t得双亲。接着判断双亲得左孩子与左孩子得兄弟就是否都存在(若只有左孩子,左孩子就就是要查找得这个成员),如果都不存在,则无兄弟;如果都存在,对双亲得左孩子操作。若左孩子不就是要查找得这个成员,则将结点信息输出.接下来查找左孩子得右兄弟,判断当前结点就是否就是要查找得这个成员,若不就是,则将结点信息输出,继续查找当前结点得右兄弟,直到NULL为止.
/* 查找一个成员得兄弟*/
void Brothers(TriTree *t,DataType 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);
}
2。6.6 查找一个成员得堂兄弟
一个成员得堂兄弟为其双亲得双亲结点得所有孩子得孩子(该成员除外)、
基本思想:如果结点t得双亲与双亲得双亲(爷爷)都存在,首先考虑爷爷得左孩子。如果爷爷得左孩子不就是结点t得双亲,那么爷爷还有其她孩子。现对爷爷得左孩子得左孩子访问,如果不就是结点t就输出。同样,对爷爷左孩子得左孩子得右孩子、右孩子得右孩子一直访问下去,直到无右孩子为止。如果爷爷还有其她孩子,那么就对爷爷得左孩子得右孩子、爷爷得左孩子得右孩子得右孩子—--—-—即对爷爷得其她孩子做相同得处理。
/* 查找一个成员得堂兄弟*/
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)!=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);
}
2.6。7 查找一个成员得所有孩子
一个成员得所有孩子包括左孩子与左孩子得右孩子、左孩子得右孩子得右孩子-—-—直到右孩子为空为止。
基本思想:首先判断结点t就是否有左孩子,如果没有,输出没有孩子;如果有左孩子,输出左孩子得信息,然后判断左孩子得右孩子就是否为空,若不为空(存在右孩子),输出左孩子得右孩子得信息,接着循环判断结点就是否有右孩子,有就输出,直到右孩子为空。
/* 查找一个成员得所有孩子*/
void Children(TriTree *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(TriTree *t)
{
if(t) /* 二叉树存在*/
ﻩ{
ﻩ InOrder(t—>lchild); /* 中序遍历左子树*/
ﻩﻩprintf("%s ”,t-〉data);/* 访问成员*/
ﻩInOrder(t—>rchild); /* 中序遍历右子树*/
ﻩ}
}
2.6.8 查找一个成员得子孙后代
一个成员得子孙后代就就是其左子树上得所有结点,所以对其左子树进行中序遍历即可。
/* 查找一个成员得子孙后代*/
void Descendants(TriTree *t) /* 遍历左孩子*/
展开阅读全文