C语言 家谱问题

C语言 家谱问题,第1张

#include<stdio.h>

#include<string.h>

char w[5][20]={{"child"},{"parent"},{"sibling"},{"descendant"},{"ancestor"}}

    int kong(char a[]) {

    int n=0,i

    for(i=0a[i]!='\0'i++) {

    if(a[i]==' ')

    n++

    else

    break

    }

    return n

}

char fam[200][20]

int num[200]={0}

int search(char a[],int n) {

    int i=1

    while(1) {

    if(!strcmp(a,fam[i]))

    return i

    i++

    }

    return 0

}

int search1(int n,int x) {

    int i=1

    while(i<x) {

    if(num[i]==n)

    return i

    i++

    }

    return 0

}

char name[1000],word[1000],n1[100],n2[100],d[100]

int main() {

    int n,m,i,j,a,b,t,x,k,h

    while(scanf("%d%d",&n,&m)!=EOF) {

        memset(fam,'\0',sizeof(fam))

        memset(num,'\0',sizeof(num))

        scanf("%s",fam[1])

        getchar()

        a=b=2

        t=1

        num[1]=1

    for(i=2i<=ni++) {

        memset(name,'\0',sizeof(name))

        gets(name)

        b=kong(name)

        if(b>a) {

            if(fam[search1(t*2+1,i)][0]!='\0')

                t=t*2+1

            else 

                t=t*2

        }

        else { if(b<a) {

            h=(a-b)/2

            while(h>=1) {

                t=t/2

                h--

            }

        }}

    if(fam[search1(t*2,i)][0]!='\0')

    x=t*2+1

    else x=t*2

    num[i]=x

    for(j=bname[j]!='\0'j++)

    fam[i][j-b]=name[j]

    a=b

    }

    for(i=0i<mi++) {

    gets(word)

    k=0h=0

    memset(n1,'\0',sizeof(n1))

    memset(n2,'\0',sizeof(n2))

    memset(d,'\0',sizeof(d))

    for(j=0word[j]!='\0'j++) {

    if(word[j]==' ') {

    k++

    h=0

    continue

    }

    if(k==0)

    n1[j]=word[j]

    if(k==5) {

    n2[h]=word[j]

    h++

    }

    if(k==3) {

    d[h]=word[j]

    h++

    }

    }

    if(!strcmp(d,w[0])) {

    a=search(n1,n)a=num[a]

    b=search(n2,n)b=num[b]

    if(a==b*2||a==(b*2+1))

    printf("True\n")

    else printf("False\n")

    continue

    }

    if(!strcmp(d,w[1])) {

    a=search(n1,n)a=num[a]

    b=search(n2,n)b=num[b]

    if(b==a*2||b==(a*2+1))

    printf("True\n")

    else printf("False\n")

    continue

    }

    if(!strcmp(d,w[2])) {

    a=search(n1,n)a=num[a]

    b=search(n2,n)b=num[b]

    if((a==b+1&&a==b/2*2+1)||(a==b-1&&b==a/2*2+1))

    printf("True\n")

    else printf("False\n")

    continue

    }

    if(!strcmp(d,w[3])) {

    a=search(n1,n)a=num[a]

    b=search(n2,n)b=num[b]

    while(a>0) {

    a=a/2

    if(a==b) {

    printf("True\n")

    break

    }

    if(a==0)

    printf("False\n")

    }

    continue

    }

    if(!strcmp(d,w[4])) {

    a=search(n1,n)a=num[a]

    b=search(n2,n)b=num[b]

    while(b>0) {

    b=b/2

    if(a==b) {

    printf("True\n")

    break

    }

    if(b==0)

    printf("False\n")

    }

    continue

    }

    }

    }

    return 0

}

听说回答的够长能够自动采纳

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

/*

*File Name: BiTree.cpp

* Author:Geng Lequn[[email protected]]

*Thur July 1 2010

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

*/

#include <iostream>

#include <string>

#include <cstring>

#include <cstdlib>

#include <vector>

#include <math.h>

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=str.find('-')e=str.find('-', b))

{

if(e == string::npos)

{

v.push_back(str.substr(b))

break

}

else

v.push_back(str.substr(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 = NULLp2 = 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 = "兄弟关系"

elsetitle = "姐妹关系"

}

elsetitle = "兄妹(姐弟)关系."

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

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

else

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

}

else//辈分不一样大

{

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

else {pbig = p2psmall = 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=0i<n++i)

tmp2 += "老"

for(int i=0i<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

}

以word 2007为例,方法如下:

1、依次单击“插入”、插图框中的“SmartArt”,在出现的对话框中选择“层次结构”、在右边出现的“组织结构图”中选中竖排或横排的结构图例,双击出现的“文本”,填写家谱姓氏辈份等信息。

2、家族人丁兴旺的可以在不同的辈份(行或列)添加多个文本,具体方法是点击想要添加位置附近文本框,在菜单栏中点击“添加形状”,在子菜单中选择在后、前、上、下添加即可。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/11324209.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-15
下一篇 2023-05-15

发表评论

登录后才能评论

评论列表(0条)

保存