Title:
41. Family relationship query Establish family relation database to realize the query of family members' closing
Design requirements:
(1) Establish family relationships and store them in files (2) Add family members (3) You can query the information of parents, ancestors, brothers, children and descendants of family members (4) The family tree is at least 5 in width and 5 in height
Data structure:
Tree is realized by Trident list and queue is chain queue
Family tree code
/*Code Author: Little Fox*/ /*Contact QQ: 1307509553*/ //Language: c++ //There are still some defects in the code. Due to personal technology, the hierarchical traversal is not used to print all member information //Printing the family tree and saving the file will only store the information of the offspring //Note: Findloc function is widely used in this code. You can use it to query the position of a member in the family tree (return a pointer) // There are some functions available at the end of the code. If you need to extend the function, you can put the function before the main function #include<iostream> #include<stdio.h> #include<string.h> #include<stdlib.h> using namespace std; #define OK 1 #define ERROR -1 #define Max 200 //String array maximum typedef struct TNode{ string Wife;//The name of the wife, if not the wife string Husband;//Husband's name, blank if there is no husband struct TNode *parent;//Parental pointer struct TNode *brother;//Brother pointer struct TNode *children;//Child pointer, only to the oldest child }tree,*Tree;//Triple linked list int AddChild(Tree &Now,string Husbandname,string Wifename);//Add child to parent node Now int AddZuXian(Tree &T,string Husbandname,string Wifename);//Adding ancestors void CaiDanMain();//Main menu interface int CheckCunZai(Tree T);//If there are members in a node, OK will be returned, otherwise ERROR will be returned int CheckFile(string file);//Judge whether the file already exists. If it exists, return OK. Otherwise, return ERROR int ChangeZuXian(Tree &T,string Husbandname,string Wifename);//Modifying the ancestors of a family int ChangeNow(Tree &Now,string Husbandname,string Wifename);//Modify the information of the current node to ensure that the current node exists void Findloc(Tree T,string &Husbandname,string &Wifename,Tree &Now);//Find the corresponding node by the name of husband and wife, Now is the pointer to record the node, recursive loop (depth traversal) void PrintTree(Tree T);//Output the lineage information of family tree int PrintChild(Tree Now);//Show all children of a node, Now is the current node int PrintParent(Tree Now);//Display the parent information of the current node. Now is the current node int PrintZuXian(Tree Now);//Display ancestor, Now is the current node int PrintBrother(Tree Now);//Show brother, Now is the current node int PrintLater(Tree Now);//Query the information of all the descendants of the current node, excluding the current node. Now is the current node int InitTree(Tree &T);//Initialize family tree int InputFile(Tree T,string file);//Save family tree to file int UploadFile(Tree &T,string file);//Overwrite family tree information from existing files int main() { Tree T; InitTree(T);//Initialization while(1) { //fox stores the option variable entered by the user. The initial value is 0 CaiDanMain();//Main menu display int fox=0;//Selection of options cout<<"Please choose: "; cin>>fox; if(CheckCunZai(T)==ERROR&&(fox>3&&fox<13))//Input first if ancestor does not exist { cout<<"Please add ancestor first!"<<endl; continue; } switch(fox) { case 0:return 0;//Exit system case 1://Select an existing file to overwrite the current family tree { while(1){ //When the value of the truth1 variable is 1, it means that the file import is successful and exits the loop; when the value is 0, the file import fails and a prompt message is displayed. Initial value is 0 string file; cout<<"Please enter the family name to import: "; cin>>file; int truth1=0; truth1=UploadFile(T,file); if(truth1==OK)//When importing family tree from file succeeded { cout<<"Successful import!"<<endl; break; } else { //When the truth2 value is 1, continue to enter the family name; when the value is 0, exit, and the initial value is 1 cout<<"Import failed!Exit press 0, re-enter family name press 1"<<endl; int truth2=1; cin>>truth2; if(truth2==0) break; } } } break; case 2://Save the current family tree to a file { //When the flag value is 1, re-enter the family name; when the flag value is 0, exit, and the initial value is 1 string file; int flag=1; while(1) { cout<<"Please enter family last name as file name: "; cin>>file; if(CheckFile(file)==OK)//When file name exists { cout<<"The family name already exists, exit press 0, re-enter family name press 1"<<endl; cin>>flag; if(flag==0) break; else continue; } if(CheckFile(file)==ERROR) break; } if(flag==0)//Exit operation break; if(CheckFile(file)==ERROR)//When the filename does not exist { InputFile(T,file);//Import family tree to file cout<<"Successful operation!"<<endl; } } break; case 3://Adding ancestors { if(CheckCunZai(T)==OK)//If ancestors already exist { cout<<"Ancestor already exists!"<<endl; } else//Enter ancestor information when it does not exist { string Husbandname,Wifename; cout<<"grandfather(Ancestors): "; cin>>Husbandname; cout<<"grandmother(Ancestors): "; cin>>Wifename; AddZuXian(T,Husbandname,Wifename); } } break; case 4://Add new family member { //Exit when the flag1 value is 0, enter the descendant information when it is not 0, and the initial value is 0 int flag1=0;//If the value is 0 - > exit this operation string Fathername,Mothername,Husbandname,Wifename; while(1)//Exit the loop when the input father and mother find it { //Exit when the flag2 value is 0, re-enter the parent information when it is not 0, and the initial value is 1 cout<<"father: "; cin>>Fathername; cout<<"mother: "; cin>>Mothername; Tree truth=NULL;//When it is NULL - > display prompt information, when it is not NULL - > Enter member information Findloc(T,Fathername,Mothername,truth); if(truth==NULL) { int flag2=1; cout<<"No parents found, exit press 0, re-enter parents press 1"<<endl; cin>>flag2; if(flag2==0) break; else continue; } else { cout<<"Search success!Member information can be entered"<<endl; flag1=1;//When the search is successful, the value is 1, and the input member information is executed break; } } if(flag1==0) break;//In case of exit, return to the main interface Tree Now;//Temporary pointer cout<<"husband: "; cin>>Husbandname; cout<<"Wife: "; cin>>Wifename; Findloc(T,Fathername,Mothername,Now);//Looking for parents' node AddChild(Now,Husbandname,Wifename);//Add children while(1) { int flag3;//Exit loop at 0 cout<<"Press 1 for the input brother and 0 for the exit system"<<endl; cin>>flag3; if(flag3==0) break; cout<<"husband: "; cin>>Husbandname; cout<<"Wife: "; cin>>Wifename; AddChild(Now,Husbandname,Wifename);//Use parent node directly } } break; case 5://Modify family ancestor { string Husbandname,Wifename; cout<<"grandfather(Ancestors): "; cin>>Husbandname; cout<<"grandmother(Ancestors): "; cin>>Wifename; ChangeZuXian(T,Husbandname,Wifename); cout<<"Modification succeeded!"<<endl; } break; case 6://Modify a family member { //Exit when the flag value is 0, reenter the member information and find the member when the flag value is 1, and the initial value is 1 string Husbandname,Wifename; int flag=1; while(1){ //When the truth value is NULL, the member does not exist. When it is not NULL, the member information is found successfully. The initial value is NULL cout<<"husband(used): "; cin>>Husbandname; cout<<"Wife(used): "; cin>>Wifename; Tree truth=NULL; Findloc(T,Husbandname,Wifename,truth); if(truth)//When the member exists { cout<<"Search success!"<<endl; break; } else//When the member does not exist { cout<<"Find failed, exit press 0, re-enter press 1!"<<endl; cin>>flag; if(flag==0) break; } } if(flag==0)break;//Exit operation Tree Now;//Temporary pointer Findloc(T,Husbandname,Wifename,Now); cout<<"husband(new): "; cin>>Husbandname; cout<<"Wife(new): "; cin>>Wifename; ChangeNow(Now,Husbandname,Wifename); } break; case 7://Show family ancestors { PrintZuXian(T); } break; case 8://Show parents of a member { //When Now is NULL, there is no member information; when not NULL, there is member information, and the initial value is NULL string Husbandname,Wifename; cout<<"husband: "; cin>>Husbandname; cout<<"Wife: "; cin>>Wifename; Tree Now=NULL;//Temporary pointer Findloc(T,Husbandname,Wifename,Now); if(Now) PrintParent(Now); else cout<<"The member information does not exist, unable to find parents!"<<endl;; } break; case 9://Show brother { while(1){ //When Now is NULL, there is no member information; when not NULL, there is member information, and the initial value is NULL string Husbandname,Wifename; cout<<"husband: "; cin>>Husbandname; cout<<"Wife: "; cin>>Wifename; Tree Now=NULL;//Temporary pointer Findloc(T,Husbandname,Wifename,Now); if(Now)//When information is found { PrintBrother(Now); break; } else//When member information is not found { //Exit when the truth value is 0, and reenter the member information when it is not 0. Initial value is 1 cout<<"No such member information, exit press 0, re-enter information press 1"<<endl; int truth=1; cin>>truth; if(truth==0) break; } } } break; case 10://Show children { while(1) { //When Now is NULL, there is no member information; when not NULL, there is member information, and the initial value is NULL string Husbandname,Wifename,Sonname,SonWifename; cout<<"husband: "; cin>>Husbandname; cout<<"Wife: "; cin>>Wifename; Tree Now=NULL;//Temporary pointer Findloc(T,Husbandname,Wifename,Now);//Node location found if(Now)//When a node is found { if(PrintChild(Now)==ERROR) { cout<<"The member has no children!,Exit press 0, re-enter information press 1"<<endl; int truth=0; cin>>truth; if(truth==0) break; } else break; } else//When member information is not found { cout<<"No such member information, exit press 0, re-enter information press 1"<<endl; int truth=0; cin>>truth; if(truth==0) break; } } } break; case 11://Show all descendants { while(1) { //When Now is NULL, there is no member information; when not NULL, there is member information, and the initial value is NULL string Husbandname,Wifename; cout<<"husband: "; cin>>Husbandname; cout<<"Wife: "; cin>>Wifename; Tree Now=NULL; Findloc(T,Husbandname,Wifename,Now); if(Now)//In existence { PrintLater(Now); break; } else//When the member does not exist { cout<<"No such member information, exit press 0, re-enter information press 1"<<endl; int truth=0; cin>>truth; if(truth==0) break; } } } break; case 12://Show family tree { PrintTree(T); } break; case 13://Clean screen operation { system("cls"); } break; default:break; } } return 0; } int AddChild(Tree &Now,string Husbandname,string Wifename)//Add child to parent node Now { if(Now->children==NULL)//Without children { Tree p;//Create a new node p=new TNode; p->brother=NULL; p->children=NULL; p->Husband=Husbandname; p->Wife=Wifename; p->parent=Now; Now->children=p; } else//When children have children { Tree now; now=Now->children;//Point to the main child while(now->brother!=NULL)//Loop through brothers now=now->brother; Tree p;//Create a new node p=new TNode; p->brother=NULL; p->children=NULL; p->Husband=Husbandname; p->Wife=Wifename; p->parent=Now; now->brother=p;//now is the last sibling node } return OK; } int AddZuXian(Tree &T,string Husbandname,string Wifename)//Adding ancestors { Tree t; t=T; t->Husband=Husbandname; t->Wife=Wifename; t->brother=NULL; t->parent=NULL; t->children=NULL; return OK; } void CaiDanMain()//Main menu interface { cout<<endl; cout<<"-----------------------------<Main menu>----------------------------------"<<endl; cout<<"| 0 Exit system |"<<endl; cout<<"| 1 Select the existing family tree to cover the current family tree |"<<endl; cout<<"| 2 File the lineage tree |"<<endl; cout<<"| 3 Adding ancestors |"<<endl; cout<<"| 4 Add new family member[The oldest brother should input first. If there is no wife, please fill in No] |"<<endl; cout<<"| 5 Modify family ancestor |"<<endl; cout<<"| 6 Modify a family member |"<<endl; cout<<"| 7 Show family ancestors |"<<endl; cout<<"| 8 Show parents of a member |"<<endl; cout<<"| 9 Show siblings of a member |"<<endl; cout<<"| 10 Show children of a member |"<<endl; cout<<"| 11 Show all descendants of a member |"<<endl; cout<<"| 12 Display lineage tree information |"<<endl; cout<<"| 13 Clean screen |"<<endl; cout<<"------------------------------------------------------------------------"<<endl; cout<<endl; } int CheckCunZai(Tree T)//If there are members in a node, OK will be returned, otherwise ERROR will be returned { Tree t;//Temporary pointer t=T; if(t->Husband==""&&t->Wife=="")//Judge the current node { return ERROR; } else return OK; } int CheckFile(string file)//Judge whether the file already exists. If it exists, return OK. Otherwise, return ERROR { //Flag is the file handle, flag = string 1.find (string 2) //When the return value of flag is string::npos, it means that string 2 is not a substring of string 1 string::size_type flag; flag=file.find(".txt"); if(flag==string::npos)//Add a suffix when there is no suffix. txt file+=".txt"; FILE*fp; char filename[Max]; strcpy(filename,file.c_str()); if((fp=fopen(filename,"r"))==NULL)//ERROR returned when not present return ERROR; else return OK; } int ChangeZuXian(Tree &T,string Husbandname,string Wifename)//Modifying the ancestors of a family { Tree t; t=T; if(t==NULL) return ERROR; t->Husband=Husbandname; t->Wife=Wifename; return OK; } int ChangeNow(Tree &Now,string Husbandname,string Wifename)//Modify the information of the current node to ensure that the current node exists { Tree now; now=Now; now->Husband=Husbandname; now->Wife=Wifename; return OK; } void Findloc(Tree T,string &Husbandname,string &Wifename,Tree &Now)//Find the corresponding node by the name of husband and wife, Now is the pointer to record the node, recursive loop (depth traversal) { if(T==NULL) return; else { if(Husbandname==T->Husband&&Wifename==T->Wife)//If the current node meets the conditions, Now points to the current node Now=T; Findloc(T->children,Husbandname,Wifename,Now);//Let's go through the children first Findloc(T->brother,Husbandname,Wifename,Now);//After that, we traverse the brothers } } void PrintTree(Tree T)//Output the lineage information of family tree { //time represents the generation of children, with an initial value of 1 Tree childs;//Temporary pointer childs=T; int time=1;//The next generation while(childs)//Cycle through children { //Cout < < the "first" < time < "generation:" < endl; if(time!=1) cout<<"The first"<<time<<"generation:"<<endl; else//Ancestor node time cout<<"The first generation(Ancestors):"<<endl; Tree brothers; brothers=childs; while(brothers)//Cycle among brothers { cout<<brothers->Husband<<"(male) "; cout<<brothers->Wife<<"(female)"<<endl; brothers=brothers->brother; } time++; childs=childs->children; } } int PrintChild(Tree Now)//Show all children of a node, Now is the current node { cout<<endl; Tree k; if(Now->children==NULL)//Error returned when no child { return ERROR; } k=Now->children; cout<<"[Children]"<<endl; while(k)//Cycle among brothers { cout<<k->Husband<<"(male) "; cout<<k->Wife<<"(female)"<<endl; k=k->brother; } return OK; } int PrintParent(Tree Now)//Display the parent information of the current node. Now is the current node { cout<<endl; Tree now; now=Now; Tree parents=NULL;//parents is a pointer to the parent of the current node if(now->parent==NULL)//If now is the ancestor node, there is no father or mother { cout<<"Now it's an ancestor, no parents!"<<endl; return ERROR; } else parents=now->parent; cout<<"[father] "; cout<<parents->Husband<<endl; cout<<"[mother] "; cout<<parents->Wife<<endl; return OK; } int PrintZuXian(Tree Now)//Display ancestor, Now is the current node { Tree k;//Temporary pointer k=Now; while(k->parent!=NULL)//Ancestor when you cycle up to a node without parents { k=k->parent; } cout<<"[Ancestors] "<<endl;//There are two ancestors cout<<k->Husband<<"(male) "; cout<<k->Wife<<"(female)"<<endl; return OK; } int PrintBrother(Tree Now)//Show brother, Now is the current node { Tree k;//Temporary pointer if(Now->parent==NULL)//In case of ancestor { cout<<"Ancestors have no brothers!"<<endl; return ERROR; } k=Now->parent->children;//Point to the main child if(k->brother!=NULL) { cout<<"[Brother] "<<endl; } else { cout<<"No brothers!"<<endl; return ERROR; } while(k)//Loop output in the siblings of the node { if(k->Husband!=Now->Husband&&k->Wife!=Now->Wife)//Do not output the member information of the current node, only the brother information { cout<<k->Husband<<"(male) "; cout<<k->Wife<<"(female)"<<endl; } k=k->brother; } return OK; } int PrintLater(Tree Now)//Query the information of all the descendants of the current node, excluding the current node. Now is the current node { //time represents the generation of children, with an initial value of 1 Tree k; if(Now->children==NULL)//No child { cout<<"No offspring information"<<endl; return ERROR; } k=Now->children; int time=1;//Represents the generation of children while(k)//Circulation in children { Tree p; p=k; cout<<"The first"<<time<<"generation:"<<endl; while(p)//Cycle in brothers { cout<<p->Husband<<"(male) "; cout<<p->Wife<<"(female)"<<endl; p=p->brother; } time++; k=k->children; } return OK; } int InitTree(Tree &T)//Initialize family tree { T=new TNode;//Create a head node T->Husband="";//Initialize to empty T->Husband=""; T->children=NULL; T->brother=NULL; T->parent=NULL; return OK; } int InputFile(Tree T,string file)//File the lineage tree { //Flag is the file handle, flag = string 1.find (string 2) //If string 2 is not a substring of string 1, the flag value is string::npos if(CheckFile(file)==OK)//Error returned when file already exists return ERROR; string::size_type flag; flag=file.find(".txt"); if(flag==string::npos)//Add suffix when there is no suffix file+=".txt"; FILE*fp; char filename[Max]; char Husbandname[Max],Wifename[Max]; char Fathername[Max],Mothername[Max]; strcpy(filename,file.c_str()); fp=fopen(filename,"w"); Tree k;//Child pointer k=T; while(k) { Tree p;//Brother pointer p=k; while(p) { if((p->Husband!=T->Husband)&&(p->Wife!=T->Wife))//When it is not an ancestor node, input the parent information { strcpy(Fathername,(p->parent->Husband).c_str()); strcpy(Mothername,(p->parent->Wife).c_str()); fprintf(fp,"%s ",Fathername); fprintf(fp,"%s\t",Mothername); } strcpy(Husbandname,(p->Husband).c_str()); strcpy(Wifename,(p->Wife).c_str()); fprintf(fp,"%s ",Husbandname);//Write current node information fprintf(fp,"%s\n",Wifename); p=p->brother; } k=k->children; } fprintf(fp,"#\n");//End sign fclose(fp);//Close file return OK; } int UploadFile(Tree &T,string file)//Overwrite the family tree information from the existing file, and return ERROR if the file does not exist { //Flag is the file handle, flag = string 1.find (string 2) //If string 2 is not a substring of string 1, the flag value is string::npos string::size_type flag;//Determine whether the suffix. txt is included flag=file.find(".txt"); if(flag==string::npos)//Add suffix.txt without suffix file+=".txt"; char filename[Max]; strcpy(filename,file.c_str());//Copy file to filename FILE*fp=fopen(filename,"r");//The passed in parameter filename is of character array type if(fp==NULL)//When the file does not exist return ERROR; char ZuFu[Max],ZuMu[Max]; fscanf(fp,"%s",ZuFu);//Store ancestor information fscanf(fp,"%s",ZuMu); string ZuFuname(ZuFu); string ZuMuname(ZuMu); AddZuXian(T,ZuFuname,ZuMuname); while(1) { char Father[Max],Mother[Max]; char Husband[Max],Wife[Max]; fscanf(fp,"%s",Father); string Fathername(Father); if(Fathername=="#") break; fscanf(fp,"%s",Mother); fscanf(fp,"%s",Husband); fscanf(fp,"%s",Wife); string Mothername(Mother); string Husbandname(Husband); string Wifename(Wife); Tree Now; Findloc(T,Fathername,Mothername,Now);//Find parent node if(Now)//When there are parent nodes AddChild(Now,Husbandname,Wifename); } fclose(fp); return OK; } /* int CountBrother(Tree Now,string Husbandname,string Wifename)//Count the number of current node brothers {//available int sum=0;//Number of brothers Tree t; if(Now->parent==NULL)//When current ancestor return 0; t=Now->parent->children; while(t) { if(t->Husband!=Husbandname&&t->Wife!=Wifename) sum++; t=t->brother; } return sum; } */ /* int InputTree(Tree &T)//Enter family members into the family tree { string Husbandname,Wifename,Fathername,Mothername; int flag1=2;//Default to need to re-enter parents cout<<"Grandfather (ancestor): "< endl; cin>>Husbandname; cout<<"Grandmother (ancestor): "< endl; AddZuXian(T,Husbandname,Wifename);//Add override ancestor cout<<"Please input the parents' information before family members input! "<<endl<<endl; while(1)//Enter family members by father and mother's name { if(flag1==2){//Need to re-enter parent information when entering new members cout<<"Please input father: "< endl; cin>>Husbandname; cout<<"Please input mother: "< endl; cin>>Wifename; } Tree Now=NULL;//Temporary node pointer Findloc(T,Fathername,Mothername,Now);//Find the node matching the parents from the family tree, and save the parents node with Now int flag2=1; if(Now==NULL)//If there are no such parents in the family tree { cout<<endl; cout<<"The parents are not found! "< endl; cout<<"-------------------------"<<endl; cout<<"| 0 Exit input | "< endl; cout<<"| 1 Re input the two parents | "< endl; cout<<"| 2 Print the existing family tree "< endl; cout<<"-------------------------"<<endl; cout<<endl; cin>>flag2; int time=1,truth=1;//time Represents the generation, truth represents the relationship between the current node and the former in recursion switch(flag2) { case 0:return OK; case 1: { cout<<"Father: cin>>Fathername; cout<<"Mother: cin>>Mothername; } break; case 2: { int time=1,flag=1; PrintTree(T,time,flag); } break; default:break; } if(flag2==2) continue; } else cout<<"Parents found successfully! Member information "< endl" can be entered; string Husband,Wife; cout<<endl; cout<<"Husband: "< endl; cin>>Husband; cout<<"Wife: "< endl; cin>>Wife; if(CheckChildren(Now)==ERROR)//If there is no child, insert it directly after the parent node { AddChild(Now,Husband,Wife); } if(CheckChildren(Now)==OK)//If there is a child, insert it behind the child's brother node { AddBrother(Now->children,Husband,Wife);//Incoming child node } cout<<endl; cout<<"------------------------"<<endl; cout<<"| 0 Exit input | "< endl; cout<<"| 1 Input brother "< endl; cout<<"| 2 Enter the new member "< endl"; cout<<"------------------------"<<endl<<endl; cin>>flag1; switch(flag1) { case 0:return OK; case 1: { } break; case 2: { } break; default:break; } } return OK; }*/ /* int AddBrother(Tree &Now,string Husbandname,string Wifename)//After adding a new member to a sibling node, the precondition: Now should be its sibling node { Tree now;//Temporary pointer now=Now; while(now->brother!=NULL)//Find the location to insert from the children of the Now node, that is, the last location of the brother node now=now->brother; Tree p; p=new TNode;//Create a node p->Husband=Husbandname; p->Wife=Wifename; p->brother=NULL; p->parent=Now; p->children=NULL; //Parents' children point to the oldest } */ /* int CheckChildren(Tree Now)//Check whether a node has children. If yes, return OK. Otherwise, return ERROR {//available Tree now; now=Now->children; if(now->Husband!=""&&now->Wife!="") return OK; else return ERROR; } int CheckBrother(Tree Now)//Check whether a node has brothers. If yes, return OK. Otherwise, return ERROR {//available Tree k;//Temporary pointer if(Now->parent!=NULL)//When not an ancestor, point to the master child { k=Now->parent;//Pointing to parents k=k->children;//Pointing brothers } else k=Now; if(k->brother==NULL) return ERROR; return OK; } */