家族关系查询系统程序设计算法思路_家族关系查询系统
家族關系查詢系統
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);
}
總結
以上是生活随笔為你收集整理的家族关系查询系统程序设计算法思路_家族关系查询系统的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: indexedDB(三)查询(详细)篇
- 下一篇: 家族关系查询系统程序设计算法思路_数据结