设计一个程序,采用二叉树表示一个家谱关系。大家知道怎么弄吗?

栏目:资讯发布:2023-10-18浏览:1收藏

设计一个程序,采用二叉树表示一个家谱关系。大家知道怎么弄吗?,第1张

(1) 文件操作功能:记录输入、记录输出,清除全部文件记录和将家谱记录存盘。

(2) 家谱操作功能:用括号表示法输出家谱二叉树,查找某人所有的儿子,查找某人所有的祖先

(3)家谱国际“修谱王”的软件很全面了,可以自己去借鉴一下哈。

/实验14—2 设计一个程序,采用二叉树表示一个家谱关系。要求程序具有如下功能:

(1) 文件操作功能:记录输入、记录输出,清除全部文件记录和将家谱记录存盘。

(2) 家谱操作功能:用括号表示法输出家谱二叉树,查找某人所有的儿子,查找某人所有的祖先。/

#include<iostreamh>

#include<stdlibh>

#include<stdioh>

#include<stringh>

typedef struct Node

{

int degree;//人员所在代数

char data;//人员标志

struct Node lchild;//data的孩子

struct Node rchild;//data的兄弟

}BTNode;

#define max 100

int choose;

char X;

void CreatBTNode(BTNode b,char str);//创建记录

BTNode SearchX(BTNode b,char X);//查找记录

void InputBTNode(BTNode b,char str);//1记录输入

void OutputBTNode(BTNode b,char str);//2记录输出

void Store(BTNode b,char str);//3家谱记录存盘

void DispTree(BTNode b);//4用括号法输出家谱

void SearchXSon(BTNode b,char X);//5查找某人的儿子

void SearchXAncestor(BTNode b,char X);//6查找某人的祖先

void Distory(BTNode b,char str);//7清除全部文件记录

int main()

{BTNode b=NULL;

char str=(char)malloc(maxsizeof(char));

str[0]='\0';

cout<<"--------------------------------------------------------------------"<<endl;

cout<<"0退出"<<endl;

cout<<"1记录输入:\t"<<endl;

cout<<"2记录输出:\t"<<endl;

cout<<"3家谱记录存盘:\t"<<endl;

cout<<"4用括号法输出家谱:\t"<<endl;

cout<<"5查找某人的儿子:\t"<<endl;

cout<<"6查找某人的祖先:\t"<<endl;

cout<<"7清除全部文件记录:\n"<<endl;

cout<<"-------------------------------------------------------------------"<<endl;

cout<<"Please choose the operation you want to do "<<endl;

cout<<"choose=";

cin>>choose;

while(choose)

{switch(choose)

{

case 1:

InputBTNode(&b,str);break;

case 2:

OutputBTNode(&b,str);break;

case 3:

Store(b,str);

printf("文件已经保存!");

break;

case 4:

DispTree(b); break;

case 5:

printf("请输入需要查找儿子的结点:");

cin>>X;

SearchXSon(b,X);

break;

case 6:

printf("请输入需要查找祖先的结点:\n");

cin>>X;

BTNode p;

p=SearchX(b,X);

if(p!=NULL)

SearchXAncestor(b,X);

else

printf("该结点不存在!");

break;

case 7:

Distory(&b,str);

printf("文件记录已经清除!");

break;

default:

cout<<endl<<"Invalid input,input again";

}

cout<<endl<<"please choose again:"<<endl;

cout<<"the choose =";

cin>>choose;

}

return 0;

}

void CreatBTNode(BTNode b,char str) //创建树

{

BTNode S[max],p=NULL;

int top=-1,tag,j=0,d=0;

char ch;

b=NULL;

ch=str[j];

while(ch!='\0')

{

switch(ch)

{

case '(':

d++;

top++;

S[top]=p;

tag=1;break;

case ')':

top--;break;

case ',':

d--;

tag=2;break;

default:

p=(BTNode )malloc(sizeof(BTNode));

p->degree=d;

p->data=ch;

p->lchild=NULL;

p->rchild=NULL;

if((b)==NULL)(b)=p;

else

{

switch(tag)

{

case 1: S[top]->lchild=p;break;

case 2: S[top]->rchild=p;break;

}

}

}

ch=str[++j];

}

}

void InputBTNode(BTNode b,char str)//记录输入

{

do

{

printf("请输入需要输入的记录:\n");

gets(str);

if(str[0]=='\0')

printf("输入的记录为空,请再次输入:\n");

}while(str[0]=='\0');

CreatBTNode(b,str);

printf("记录创建成功!");

}

void OutputBTNode(BTNode b,char str)//从文件中读出记录

{

FILE fp;

if((fp=fopen("wangljtxt","r"))==NULL)

{

printf("不存在记录文件,要建立吗\n建立请输入Y,否则按其他键:");

if(getchar()=='Y')

{

fp=fopen("wangljtxt","w+");

printf("记录文件“wangljtxt”已建立\n");

}

else

exit(1);

}

else

{

if(!feof(fp))

fscanf(fp,"%s",str);

fclose(fp);

CreatBTNode(b,str);

printf("文件中记录已输出\n");

}

}

void Store(BTNode b,char str)//储存全部的结点记录

{

BTNode p;

p=b;

FILE fp;

fp=fopen("wangljtxt","w+");

if(fp==NULL)

{

printf("文件打开失败!");

return;

}

else

{

if(p!=NULL)

{

fprintf(fp,"%s",str);

fclose(fp);

}

}

}

void DispTree(BTNode b)//用括号法输出家谱记录

{

if(b!=NULL)

{printf("%c",b->data);

if(b->lchild!=NULL||b->rchild!=NULL)

{printf("(");

DispTree(b->lchild);

if(b->rchild!=NULL)

{printf(",");

DispTree(b->rchild);

}

printf(")");

}

}

else

printf("\0");

}

BTNode SearchX(BTNode b,char X)//查找结点X

{BTNode p;

if(b==NULL) return NULL;

else if(b->data==X) return b;

else

{

p=SearchX(b->lchild,X);

if(p!=NULL) return p;

else

{

return SearchX(b->rchild,X);

}

}

}

void SearchXSon(BTNode b,char X)//查找结点X的所有儿子

{

BTNode p,q;

p=SearchX(b,X); //找到节点X

if(p!=NULL)

{

p=p->lchild;

if(p==NULL) //X没有孩子

printf("节点%c没有儿子!",X);

else

{

printf("节点%c的所有儿子为:",X);

if(p!=NULL)

printf("%c ",p->data);

q=p->rchild;

while(q)

{

printf("%c ",q->data);

q=q->rchild;

}

}

}

else

printf("该结点不存在!");

}

void TraverseBT(BTNode b,int d)//遍历家谱

{

if(b!=NULL)

if(b->degree<d)

{

printf("%c ",b->data);

if(b->lchild!=NULL)

TraverseBT(b->lchild,d);

if(b->rchild!=NULL)

TraverseBT(b->rchild,d);

}

}

void SearchXAncestor(BTNode b,char X)//查找结点X的所有祖先

{

if(b==NULL)

{

printf("这是一棵空树!");

return ;

}

BTNode p=SearchX(b,X);

if(p->degree==0)

{

printf("X为根节点或其兄弟,没有祖先!");

return;

}

printf("%c结点的祖先有:",X);

TraverseBT(b,p->degree);

}

void Distory(BTNode b,char str)//清除全部的记录

{

(b)=NULL;

FILE fp;

fp=fopen("wangljtxt","w");

if(fp==NULL)

{

printf("打开文件失败!");

exit(1);

}

str="";

fclose(fp);

}

你懂的,同道中人!

C++语言: 二叉树实现的简单家谱树

/

File Name: BiTreecpp

Author: Geng Lequn[glq2000@126com]

Thur July 1 2010

Discription: 建立二叉家谱树,实现输入任意两个人的名字,查找得到其关系

/

#include <iostream>

#include <string>

#include <cstring>

#include <cstdlib>

#include <vector>

#include <mathh>

using namespace std;

typedef struct _Node

{

string sex; //性别 m 男; f 女

string name; //此人的姓名

string spause; //配偶的姓名

unsigned short level; //层次 辈分最高一层为1,下一层为为2,以此类推

struct _Node l_child; //指向其第一个孩子的指针

struct _Node r_brother; //指向其某一个兄弟姐妹的指针, 即左孩子为其后代,右孩子为其兄弟姐妹

struct _Node btr; //指向其父亲或者母亲的指针

_Node():level(0),l_child(NULL),r_brother(NULL),btr(NULL){cout<<"constructor"<<endl;}

~_Node(){cout<<name<<" destructor"<<endl;}

}Node, PNode;

void CreateBiTreePreOrder(PNode &pn, PNode pback, unsigned short depth);//建立二叉家谱树,以先序方式

void VisitBiTreePreOrder(PNode root); //前序遍历此二叉树

void TellRelation(PNode root); //判断两人关系

void DestroyBiTreePostOrder(PNode root); //销毁二叉树,释放节点占用的空间

void FindPersonMiddleOrder(PNode root, string name, PNode &presult); //返回家谱中指向某人的指针,找不到返回NULL

Node root=NULL; //全局变量,二叉树的根节点

unsigned findPersonFlag = 0; //标志位,0 没找到; 1 找到,找到后就不再搜索直接返回;利用此flag可避免将整个tree遍历一遍(若该name在tree中存在的话)

int main()

{

cout<<"请按先序遍历的顺序根据提示输入家谱信息,不存在则输入\"#\""<<endl;

CreateBiTreePreOrder(root, NULL, 1);//建立二叉家谱树,以先序方式

VisitBiTreePreOrder(root); //前序遍历此二叉树

TellRelation(root); //判断两人关系

DestroyBiTreePostOrder(root); //销毁二叉树

getchar();getchar();getchar();

return 0;

}

/

function:建立二叉家谱树,以先序方式

argument:

pn: 指向二叉树节点的引用

pback: pn这个节点的btr指针的值,即指向其parent的指针

depth: 该节点的层次,分最高一层为1,下一层为为2,以此类推

/

void CreateBiTreePreOrder(PNode &pn, PNode pback, unsigned short depth)

{

string str;

cin>>str; //输入该人信息,格式是 sex-name-spausename,如不存在则输入#

if(str == "#") //如: M-tom-marry, 表示此人叫tom, 男性, 配偶名字marry

{

pn = NULL;

return;

}

//如果是自定义的struct/class,应该使用构造函数。如果是内建数据类型,

//比如int,应该memset。 当然,更好的建议是使用vector取代new出来的数组

pn = new Node;

//处理输入的字符串

vector<string> v;

for(size_t b=0, e=strfind('-'); ; e=strfind('-', b))

{

if(e == string::npos)

{

vpush_back(strsubstr(b));

break;

}

else

vpush_back(strsubstr(b, e-b));

b = e+1;

}

//初始化该节点

pn->sex = v[0];

pn->name = v[1];

pn->spause = v[2];

pn->btr = pback;

pn->level = depth;

//递归建立左右子树的节点

CreateBiTreePreOrder(pn->l_child, pn, depth+1); //注意后两个参数的值

CreateBiTreePreOrder(pn->r_brother, pback, depth); //注意后两个参数的值

}

/

function: 前序遍历此二叉树

/

void VisitBiTreePreOrder(PNode pn)

{

if(!pn)

return;

cout<<endl<<"sex:"<<pn->sex<<endl;

cout<<"name:"<<pn->name<<endl;

cout<<"spause:"<<pn->spause<<endl;

cout<<"level:"<<pn->level<<endl;

cout<<"father's name:"<<((pn->btr == NULL)"NULL":pn->btr->name)<<endl;

cout<<"======================"<<endl;

VisitBiTreePreOrder(pn->l_child);

VisitBiTreePreOrder(pn->r_brother);

}

/

function: 中序遍历找到家谱中的一个人,返回其指针,若找不到,返回NULL

isSpause 1表示是找到的节点的配偶 0表示不是所找到的节点的配偶

/

void FindPersonMiddleOrder(PNode pn, string name, PNode &presult)

{

if(!pn)

return;

FindPersonMiddleOrder(pn->l_child, name, presult);

if(findPersonFlag) return;

if(name == pn->name || name == pn->spause)

{

presult = pn;

findPersonFlag = 1; //全局标志位,0 没找到; 1 找到,找到后就不再搜索直接返回;利用此全局flag可避免将整个tree遍历一遍(若该name在tree中存在的话)

return; //下次使用前不要忘记置为0

}

FindPersonMiddleOrder(pn->r_brother, name, presult);

}

/

function: 判断两人关系,若两人中至少一人不在树中,则两人无关系

若两人在树中,先判断两人是否同层次,若同层,判断是否是亲兄弟姐妹;

若不同层,设辈分大的人为A,辈分小的人为B,判断A和B是亲的还是表的,

比如,A为男性,且比B大一倍,判断A是否为B的爸爸,或亲叔叔(舅舅),或表叔叔(舅舅)

简单起见,此处没有区分是叔叔还是舅舅

比如,A为男性,且比B大两倍,判断A是否为B的亲爷爷(姥爷),或亲爷爷(姥爷)的亲兄弟

,或亲爷爷(姥爷)的表兄弟

简单起见,此处没有区分是叔叔和舅舅等做进一步区分

简单起见,查询时只输入节点中的name,不查询spause,否则处理起来太麻烦

/

void TellRelation(PNode pn)

{

string name1, name2;

//p1指向name1, p2指向name2, pbig指向辈分大的,psmall指向辈分小的

PNode p1 = NULL, p2 = NULL, pbig = NULL, psmall = NULL;

int differ = 0; //两人辈分数的差别

string title;

Label:

cout<<endl<<"输入想查询关系的两个人的名字,不想查则将两人名字输成#:"<<endl;

while(cin>>name1 && cin>>name2)

{

if(name1=="#" && name2=="#") return;

p1 = NULL; p2 = NULL; //因为程序是循环执行的,需要将上次遗留的值清掉

findPersonFlag = 0;

FindPersonMiddleOrder(root, name1, p1);

findPersonFlag = 0;

FindPersonMiddleOrder(root, name2, p2);

if(!p1 || !p2) //若有一个为空或都为空,说明至少有一个人不在家谱中,故两人无亲缘关系

{

cout<<name1<<((!p1)" 不在":" 在")<<" 家谱树中"<<endl;

cout<<name2<<((!p2)" 不在":" 在")<<" 家谱树中"<<endl;

cout<<name1<<" 和 "<<name2<<" 间没有关系"<<endl<<endl;

goto Label;

}

differ = (int)abs(p1->level - p2->level);

if(!differ) //辈分一样大

{

if(p1->sex == p2->sex)

{

if(p1->sex == "M") title = "兄弟关系";

else title = "姐妹关系";

}

else title = "兄妹(姐弟)关系";

if(p1->btr == p2->btr) //parent相同

cout<<name1<<" 和 "<<name2<<" 间是 "<<" 亲 "<<title<<endl;

else

cout<<name1<<" 和 "<<name2<<" 间是 "<<" 表 "<<title<<endl;

}

else //辈分不一样大

{

if(p1->level < p2->level) {pbig = p1; psmall = p2;}

else {pbig = p2; psmall = p1;}

switch(differ)

{

case 1:

if(psmall->btr == pbig)

title = ((pbig->sex == "M")"爸爸":"妈妈");

else

{

if(psmall->btr->btr == pbig->btr)

title = ((pbig->sex == "M")"亲叔(舅)":"亲姑(姨)");

else

title = ((pbig->sex == "M")"表叔(舅)":"表姑(姨)");

}

break;

case 2:

if(psmall->btr->btr == pbig)

title = ((pbig->sex == "M")"爷爷(姥爷)":"奶奶(姥姥)");

else

{

string tmp = ((pbig->sex == "M")"兄弟":"姐妹");

if(psmall->btr->btr->btr == pbig->btr)

title = ((psmall->btr->btr->sex == "M")"爷爷(姥爷)的亲":"奶奶(姥姥)的亲") + tmp;

else

title = ((psmall->btr->btr->sex == "M")"爷爷(姥爷)的表":"奶奶(姥姥)的表") + tmp;

}

break;

default:

string tmp2;

PNode pt = psmall;

int n = differ-2; //计算"老"字 (即grand这个字) 出现的个数

for(int i=0; i<n; ++i)

tmp2 += "老";

for(int i=0; i<differ; ++i)

pt = pt->btr;

if(pt == pbig)

title = tmp2 + ((pbig->sex == "M")"爷爷(姥爷)":"奶奶(姥姥)");

else

{

string tmp3 = ((pbig->sex == "M")"兄弟":"姐妹");

if(pt->btr == pbig->btr)

{title = tmp2 + ((pt->sex == "M")"爷爷(姥爷)的亲":"奶奶(姥姥)的亲"); title+=tmp3;}

else

{title = tmp2 + ((pt->sex == "M")"爷爷(姥爷)的表":"奶奶(姥姥)的表"); title+=tmp3;}

}

break;

}

cout<<pbig->name<<" 是 "<<psmall->name<<" 的 "<<title<<endl;

}

goto Label;

}

}

/

function: 后序遍历销毁此二叉树,释放节点占用的内存空间

/

void DestroyBiTreePostOrder(PNode pn)

{

if(!pn) return;

DestroyBiTreePostOrder(pn->l_child);

DestroyBiTreePostOrder(pn->r_brother);

delete pn;

}

画家谱思维导图的步骤如下:

确定家族中最早的共同祖先,将其放在画布中心位置。根据共同祖先的儿子和女儿,绘制第二层次的节点,并连接到共同祖先。从第二层次节点出发,依次绘制第三层次、第四层次等节点,并连接到它们的父母节点。在每个节点上标注姓名、生卒年月等信息。根据需要添加符号或颜色区分家庭成员的性别、配偶等关系。

此外,绘制思维导图,可以借助极简式专业思维导图软件-『MindNow思维导图』。

1、简约易用,多端互通,小白一秒上手

简约的界面风格,非常适合新手小白使用,操作简单,具有在线版本与客户端,电脑不在身边的,还可以使用手机微信小程序版本,文件实时同步;

2、导图设置丰富,灵活自由度高,激发创造性思维灵感

40+快捷键流畅操作 12种布局,26种主题背景,美观有个性 支持插入,外链,数学公式,添加附件,概要,无节点限制,导图和大纲一键切换!

3、超丰富模板,一键套用

海量知识模板库,覆盖读书笔记、职场技能、考研考证等20+细分领域,满足企业及个人知识库的多方位需求。

4、云端存储,多格式导出,一键分享

支持云端实时存储,多端互通,一键分享,多格式导出,文件夹可加密,可设置偏好设置等,是更专业的思维导图软件!

设计一个程序,采用二叉树表示一个家谱关系。大家知道怎么弄吗?

(1) 文件操作功能:记录输入、记录输出,清除全部文件记录和将家谱记录存盘。(2) 家谱操作功能:用括号表示法输出家谱二叉树,查找某...
点击下载
热门文章
    确认删除?
    回到顶部