求用C++表示二叉树 家谱

栏目:资讯发布:2023-11-03浏览:1收藏

求用C++表示二叉树 家谱,第1张

//是找所有的子孙吗?还是所有儿子

//这里写个所有子孙的吧,所有儿子更容易

void findChild( TreeNode root, char name, bool flag )

{

if( !root )

{

return ;

}

else if( !lstrcmp( root->name, name ) ) //找到某个人

{

flag = true;

}

if( flag )

{

cout<< root->name<<",";

}

findChild( root->leftChild, name, flag );

findChild( root->rightChild, name, flag );

}

void findParent( TreeNode root, char name, bool flag )

{

if( !root )

{

return false;

}

if( !lstrcmp( root->name, name ) )

{

flag = true;

}

if( flag )

{

findParent( root->parent, name, tag );

cout<<root->name<<",";

}

else

{

findParent( root->leftChild, name, tag );

findParent( root->rightChild, name, tag );

}

}

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;

}

完整的家谱一般包括:谱序,首事名录,字辈世系行号,家训,家谱中当然看把每个家族成员记载进去啊。

简言之,每个家族都有不同的族规家训。家谱中较为常见者,大致包括了以下内容:(一)、注重家法、国法(二)、和睦宗族、乡里(三)、孝顺父母、敬长辈(四)、合乎礼教、正名分(五)、祖宗祭祀、墓祭程序。

总之关于修家谱的东西很多, 需要修谱的朋友还是建议找专业的修谱的人咨询。-百姓通谱

家谱可不是随便编的。编家谱实际应是续家谱。一般的家谱都是有章法的,依着字号顺序排列。当字号用完或即将用完时,应有几位本家性氏的年长老者,举行续家谱仪式,共同商定往下排续的字号,而选续的字号决不允许与先辈的字号重复。

例如:常永志--“常”是姓氏,永志是名字,“永”就是永字辈的家谱字号。而字号用在名字的第一位或第二位均可。

如果老师让你们编家谱的话,那么你们的老师是个白痴。

家谱的主要内容:姓氏源流和世系表。

一、姓氏源流

中国姓氏在经过历史不断演变,如:战乱,迁移,改朝换代,以及避讳改姓、避难改姓、复姓改为单姓等,姓氏变得更为复杂,其真正的出处、源头就更需要详细考证了。一些史学专家认为,历史上的王朝更替、社会动荡导致了家谱的断裂残缺,很多族谱都由后人凭想象臆造。

封建时代,许多姓氏为了抬高自己的门第和郡望,习惯于与名人扯上关系,或硬追溯到某皇帝作自己的祖先,这影响了血缘的纯正性和确实性。重视传统的中华民族,有不少家族在重修宗谱,由于南北各地的语言、风俗、长相等均不同,世系联系在一起,其纸谱真实性值得推敲。

二、世系表

作为家谱中最重要的内容,“世系表”,简而言之,就是说明一个家族成员,如:父子、兄弟间的相互关系,写清楚祖先后代每一个家族成员名字的图表。它有四种基本的记述格式:欧式、苏式、宝塔式和牒记式。

(1)欧式:又称横行体,是北宋文学家欧阳修创立的。欧式的特点是:世代分格,由右向左横行,五世一表,用起来很方便。欧式中,每个世代人名左侧都有一段生平记述,介绍该人的字、号、功名、官爵、生辰年月日、配偶、葬地、功绩等。

(2)苏式:又称垂珠体,是北宋文学家苏洵创立的。苏式世系表的特点是:世代直行下垂,世代间无横线连接,全部用竖线串连,图表格式也是由右向左排列的,主要是强调宗法关系。

(3)宝塔式:顾名思义,就是将世代人名象宝塔一样,由上向下排列。宝塔式采用横竖线连接法,竖线永远处在横线的中间,这对人多的大家族来说,因人名不可能排在同一页纸上,兄弟之间长幼关系不清,会为写谱、看谱带来很多不便。

(4)牒记式:不用横竖线连接世代人名间的关系,而是纯用文字来表述这种关系。每个人名下都有一个相关的简介,如:字、号、功名、官爵、生辰年月日、葬地、功绩等。牒记式的世系形式固定,次序分明,比较节约纸张。

扩展资料

家谱是一个家族的历史记载,通过家谱,能够了解当时的历史面貌、时代精神、社会风尚,了解在那个历史背景下人们的生产、生活情况。相传它是由正史中的帝王本纪及王侯列传、年表等演变而来。家谱是和正史、方志一样重要的历史典籍,是史学的重要组成部分之一。

中国的家谱一般都有家规族训,对于规范人生和教育子弟有着积极的意义。家谱,亦称族谱、宗谱、家乘、通谱、统谱、世谱、支谱、房谱等等,名称各异,其内涵是同一的,只是外延有所区别而已,如今一般统称家谱或族谱。家谱是系统记述某一同宗共祖的血缘集团世系人物或兼及其他方面情况的历史图籍。而姓氏是“某一同宗共祖血缘集团”的标识符号,家谱、族谱就是记录某一姓氏家族成员间的血缘关系的图册。

-家谱 (人文资料)

除了平时老板交代的任务外不知道思维导图怎么用?至少可以帮你起一个不落俗套的名字哟。最近我看到一个有趣的新闻,近年来相当一部分父母给孩子起名越来越“琼瑶”了。

其实这种琼瑶式名字没有什么不好,但数量增长到一定程度就会让人觉得千篇一律、没有特点。这怎么符合小孩子希望的天上天下我最独特的中二想法呢?

所以我特意准备了一个关于名字的思维导图案例,告诉大家起名字的那些套路,下面的这个案例主要是通过思维导图软件MindManager来创立的,可以点击这里下载MindManager思维导图软件。

在起名字这个事情上,一般有一下几个套路可以遵循:

“听到名字就醉了”系列,有个很传统的法则是:文论语,武周易;女诗经,男楚辞。我已经准备了几十个有出处且富有诗意的名字,就差孩子了!

这种情况就比较复杂了,毕竟父母想什么的都有。但还是不要寄希望于起个名字就改变人生吧,叫旺财的那么多,然而……

计划生育前每个家里孩子数量没有限制,这么多孩子起名也是个麻烦事,干脆打包命名吧!这种起名方式通常见于大家族,同一辈分的孩子名字相互关联,不同辈分也会依照家谱延续下去。

看看上图那些坑娃的名字,我不自觉开始同情这些祖国未来的花朵,甚至可以听到这些孩子长大后内心的咆哮:爸爸妈妈难道你们不爱我么!

上图为起名套路思维导图案例全图,其实大家平时可以多探索下思维导图怎么用,在发散思维这个领域思维导图软件可以说是独领 ,不仅是工作学习中,平时生活上的大小事情也都可以使用思维导图整理思路、梳理结构。

求用C++表示二叉树 家谱

//是找所有的子孙吗?还是所有儿子 //这里写个所有子孙的吧,所有儿子更容易 void findChild( TreeNode ...
点击下载
热门文章
    确认删除?
    回到顶部