家族关系查询系统程序设计算法思路_家族关系查询系统
家族关系查询系统
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<
getchar();
gets(str);
tree=Create(str);
break;
case 2:
cout<
getchar();
gets(str);
tree=Open(str);
break;
case 3:
Append(tree);
break;
case 4:
Ancestor(tree);
break;
case 5:
cout<
cin>>str;
temp=Search(tree,str);
if(!temp) // 若不存在则返回
{
printf("该成员不存在!\n");
continue;
}
AncestorPath(temp);
break;
case 6:
cout<
cin>>str;
temp=Search(tree,str);
if(!temp) // 若不存在则返回
{
printf("该成员不存在!\n");
continue;
}
Generation(temp);
break;
case 7:
cout<
cin>>str;
temp=Search(tree,str);
if(!temp) // 若不存在则返回
{
printf("该成员不存在!\n");
continue;
}
Parent(temp);
break;
case 8:
cout<
cin>>str;
temp=Search(tree,str);
if(!temp) // 若不存在则返回
{
printf("该成员不存在!\n");
continue;
}
Brothers(temp,str);
break;
case 9:
cout<
cin>>str;
temp=Search(tree,str);
if(!temp) // 若不存在则返回
{
printf("该成员不存在!\n");
continue;
}
Consin(temp);
break;
case 10:
cout<
cin>>str;
temp=Search(tree,str);
if(!temp) // 若不存在则返回
{
printf("该成员不存在!\n");
continue;
}
Children(temp);
break;
case 11:
cout<
cin>>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
{
num=parpos-count;
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;
}
else
{
for(j=i; j>=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<
}
else
cout<
}
}
void Ancestor(Tree *t) //祖先
{
printf("该家族的祖先为%s\n",t->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);
}
家族关系查询系统程序设计算法思路_家族关系查询系统相关推荐
- 家族关系查询系统程序设计算法思路_【学习笔记】数据库基础 - 查询优化
目录 什么是数据库查询优化? 影响查询优化的因素 优化策略概述 查询优化的总体思路 语义优化 -- 内容等价性 语法优化(逻辑层优化)---语法等价性 执行优化(物理层优化) 查询优化在DBMS中的位 ...
- 家族关系查询系统程序设计算法思路_数据结构课程设计--
数据结构课程设计-- 家族关系查询系统 课 程 设 计 任 务 书 题目题目 家族关系查询系统家族关系查询系统 主要内容.基本要求.主要参考资料等主要内容.基本要求.主要参考资料等 主要内容主要内容 ...
- 家族关系查询系统程序设计算法思路_数据结构课程设计(家族关系查询系统)
1 课程设计介绍 1 . 1 课程设计项目简介 家谱就是一种以表谱形式 , 记载一个以血缘关系为主体得 家族世系繁衍与重要人物事迹得特殊图书载体.家谱就是中国特 有得文化遗产,就是中华民族得三大文献之 ...
- 家族关系查询系统程序设计算法思路_数据结构课程设计方案(家族关系查询系统)...
家族关系查询系统 1 1 课程设计介绍 1.1 课程设计项目简介 家谱是一种以表谱形式, 记载一个以血缘关系为主体的家族世 系繁衍和重要人物事迹的特殊图书载体.家谱是中国特有的文化 遗产,是中华民族的 ...
- 家族关系查询系统程序设计算法思路_数据结构课程设计(家族关系查询系统).....
家族关系查询系统 1 1 课程设计介绍 1.1 课程设计项目简介 家谱是一种以表谱形式, 记载一个以血缘关系为主体的家族世 系繁衍和重要人物事迹的特殊图书载体.家谱是中国特有的文化 遗产,是中华民族的 ...
- 家族关系查询系统程序设计算法思路_大数据结构课程设计(家族关系查询系统)要点...
实用标准文案 精彩文档 1 课程设计介绍 1.1 课程设计项目简介 家谱是一种以表谱形式, 记载一个以血缘关系为主体的家族世 系繁衍和重要人物事迹的特殊图书载体.家谱是中国特有的文化 遗产,是中华民族 ...
- 家族关系查询系统程序设计算法思路_七大查找算法(附C语言代码实现)
来自:Poll的笔记 - 博客园 链接:http://www.cnblogs.com/maybe2030/p/4715035.html 阅读目录 1.顺序查找 2.二分查找 3.插值查找 4.斐波那契 ...
- 家族关系查询系统程序设计算法思路_数据结构课程设计(家族关系查询系统)..doc...
数据结构课程设计(家族关系查询系统). 1 课程设计介绍 1.1课程设计项目简介 家谱是一种以表谱形式,记载一个以血缘关系为主体的家族世系繁衍和重要人物事迹的特殊图书载体.家谱是中国特有的文化遗产,是 ...
- 家族关系查询系统程序设计算法思路_数据结构课程设计家族关系查询系统要点...
家族关系查询系统 1 课程设计介绍 1.1 课程设计项目简介 家谱是一种以表谱形式,记载一个以血缘关系为主体的家族世系繁衍和重要 人物事迹的特殊图书载体. 家谱是中国特有的文化遗产, 是中华民族的三大 ...
最新文章
- Django源码分析6:auth认证及登陆保持
- pthread_create函数编译时报错:undefined reference to 'pthread_create'
- vue 修改favicon
- Office 2007 小技巧
- vj p1038题解
- mysql.h说明文档,mysql.h:没有文件或目录
- MySQL必知必会——数据库基础知识和MySQL基本使用
- 神经网络编程的34个案例,神经网络编程是什么
- Centos7下安装yasm详细步骤
- 左/右移运算符,循环左/右移运算
- 立创eda学习笔记二十九:原理图转PCB
- 二维码被扫实时返回方案
- 水果店做生意不好怎么办,水果店生意不好如何做好
- rtl语言_21个最佳RTL WordPress主题(从右到左语言)
- Python的学习笔记案例8--空气质量指数计算6.0
- 博升机器人_乐博乐博机器人
- Maven配置nexus私服地址
- 用java求水仙花数,适合新手
- LeetCode—494. 目标和(Target Sum)——分析及代码(Java)
- iPhone 13锁屏无法收到微信通知提示怎么解决?
热门文章
- Legacy octal literals are not allowed in strict mode
- 我的大学计算机课 作文,我的大学第一课
- 3GQQ幻想西游升级最快的方法(集)
- android录音波浪动画_Android语音输入的波浪效果 – WaveView
- 【转】我们为什么要使用 Markdown
- 中国IT研发实力最强的城市分析(转载)
- 在anaconda设置Python的IDEL编辑器
- RecycleView 二级列表(多级列表)
- 阿里Java代码规范
- python多任务、面向对象、命令行启动动态绑定端口号静态web服务器代码实现