17-3难

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define NAMESIZE 20

typedef struct TreeNode{
    char name[NAMESIZE];        //自己的名字
    int gradation;              //自己的辈分 即树的深度
    char parent[NAMESIZE];      //祖先的名字
    TreeNode* leftchild;        //左孩子
    TreeNode* rightchild;       //右孩子
}TreeNode;

void GetName(char* str, int index, char* parent, char* leftc, char* rightc);        //根据字符串划分各个人的名字
TreeNode* AddTreeNode(TreeNode* root, char* parent, char* leftc, char* right);      //往树中添加节点
TreeNode* FindTreeNode(TreeNode* root, char* parent);                               //根据名字查找树节点
bool IsSame(char* a, char* b);                                                      //判断两个字符串是否相同
void FindRelation(TreeNode* root, char* person1, char *person2);                    //找两个人的关系

int main(){
    TreeNode* root = NULL;
    char ch;
    int tag = 0;
    char parent[NAMESIZE], leftc[NAMESIZE], rightc[NAMESIZE];   //存储每行中输入的父母,孩子
    while( tag == 0 && (ch = getchar()) != EOF ){
        parent[0] = leftc[0] = rightc[0] = '\0';
        char str[3 * NAMESIZE];                                 //存储一行的字符串
        int index = 0;
        while(ch != '\n'){
            str[index++] = ch;
            ch = getchar();
        }
        str[index] = '\0';
        //printf("%s\n", str);
        GetName(str, index, parent, leftc, rightc);             //将一行字符串分解为父母,孩子
        //printf("%s\t%s\t%s\n", parent,leftc, rightc);
        if(strlen(rightc))                                      //如果只输入两个人,就找关系,三个人就添加到树中
            root = AddTreeNode(root, parent, leftc, rightc);    //将新节点加入二叉树中
        else{
            FindRelation(root, parent, leftc);                  //找关系
            tag = 1;
        }
    }

    return 0;
}

void GetName(char* str, int index, char* parent, char* leftc, char* rightc){
    int i;
    int tag = 0;
    for(i = 0; i < index; ){
        while(str[i] == ' ')        //跳过多个空格
            ++i;
        while(str[i] != ' ')
            parent[tag++] = str[i++];   //祖先
        parent[tag] = '\0';

        tag = 0;
        while(str[i] == ' ')        //跳过多个空格
            ++i;
        while(str[i] != ' ' && i < index)
            leftc[tag++] = str[i++];    //左孩子
        leftc[tag] = '\0';

        tag = 0;
        while(str[i] == ' ')        //跳过多个空格
            ++i;
        while(str[i] != ' ' && i < index)
            rightc[tag++] = str[i++];   //右孩子
        rightc[tag] = '\0';
    }
}

TreeNode* AddTreeNode(TreeNode* root, char* parent, char* leftc, char* right){
    if(root == NULL){       //根节点
        root = (TreeNode* )malloc(sizeof(TreeNode));
        strcpy((root->name), parent);
        root->parent[0] = '\0';
        root->gradation = 0;
        root->leftchild = NULL;
        root->rightchild = NULL;
    }

    TreeNode* temp = FindTreeNode(root, parent);
    //printf("%s\n", temp->name);

    TreeNode *lc = (TreeNode* )malloc(sizeof(TreeNode));                
    strcpy((lc->name), leftc);      //创建左孩子
    strcpy(lc->parent,parent);
    lc->gradation = temp->gradation + 1;
    lc->leftchild = NULL;
    lc->rightchild = NULL;

    TreeNode *rc = (TreeNode* )malloc(sizeof(TreeNode));
    strcpy(rc->name, right);        //创建右孩子
    strcpy(rc->parent,parent);
    rc->gradation = temp->gradation + 1;
    rc->leftchild = NULL;
    rc->rightchild = NULL;

    temp->leftchild  = lc;      //连接
    temp->rightchild = rc;

    return root;
}


TreeNode* FindTreeNode(TreeNode* root, char* parent){   //先序遍历 查找name为parent的树节点
    if(root == NULL)    
        return NULL;
    if(IsSame(root->name, parent)){
        return root;
    }
    TreeNode* result = FindTreeNode(root->leftchild, parent);
    if(result == NULL)
        result = FindTreeNode(root->rightchild, parent);
    return result;
}

bool IsSame(char* a, char* b){                          //判断两个字符串是否相同
    int len1 = strlen(a);
    int len2 = strlen(b);
    if(len1 != len2)
        return false;
    for(int i = 0; i < len1; i++)
        if(a[i] != b[i])
            return false;
    return true;
}

void FindRelation(TreeNode* root, char* person1, char *person2){    //找两个人的关系
    TreeNode* p1 = FindTreeNode(root, person1);
    TreeNode* p2 = FindTreeNode(root, person2);

    TreeNode* min;
    TreeNode* max;
    if(p1->gradation > p2->gradation){  //p1的层次更深,辈分更小
        min = p1; max = p2;
    }else{
        min = p2; max = p1;         
    }

    int level = min->gradation - max->gradation;    //小辈分(高层次) - 高辈分(低层次)
    while(min->gradation > max->gradation){         //当两个人辈分不一样时,小辈分向上'爬'
        char *parent = min->parent;                 //直到两个 人辈分(层次)一样
        min = FindTreeNode(root, parent);
    }
    while( !IsSame(min->parent, max->parent) ){     //两个人层次一样时,如果祖先不一样,则处于不同的子树中
        char *parent = min->parent;                 //两个都需要同时向上'爬',直到祖先一样,或者'爬'到根节点
        min = FindTreeNode(root, parent);
        parent = max->parent;
        max = FindTreeNode(root, parent);
    }
    if(min->gradation == 0)
        printf("没有共同祖先 %d\n", level);
    else
        printf("%s %d\n", min->parent, level);

}
//2018/3/13
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<ctype.h>

#define NAME 20

//建立一棵二叉树
struct node
{//每个树节点包括
	char name[NAME];	//自己节点的名字
	node* lc;	//左孩子指针
	node* rc;	//右孩子指针
	char pname[NAME];	//父节点名字
	int generation;	//自己的树深
};

bool IsWord(char a)//判断是不是字符
{
	if(a>'a'&&a<'z'||a>'A'&&a<'Z'||a=='_')
		return true;
	return false;
}

void GetName(char str[100],int index,char* parent,char* lchild,char* rchild)//切分字符串中的名字
{
	int i=0,j=0;
	while(IsWord(str[i]))
	{
		parent[j++]=str[i++];
	}
	parent[j]='\0';
	while(!IsWord(str[i]))
		i++;

	j=0;
	while(IsWord(str[i]))
	{
		lchild[j++]=str[i++];
	}
	lchild[j]='\0';
	while(!IsWord(str[i])&&i<index)
		i++;

	j=0;
	while(IsWord(str[i])&&i<index)
	{
		rchild[j++]=str[i++];
	}
	rchild[j]='\0';
	while(!IsWord(str[i])&&i<index)
		i++;
}

bool IsSame(char *a,char *b)//判断名字是否相同
{
	int len1=strlen(a);
	int len2=strlen(b);
	if(len1!=len2)
		return false;
	int i;
	for(i=0;i<len1;i++)
	{
		if(a[i]!=b[i])
			return false;
	}
	return true;
}

node* FindNode(node* root,char* parent) //先序遍历 查找name为parent的树节点
{
	if(root==NULL)
		return NULL;

	if(IsSame(root->name,parent)) //先序遍历根节点
		return root;
	else
	{
		node* result = FindNode(root->lc,parent);//先序遍历左孩子
		if(result==NULL)
			result=FindNode(root->rc,parent);//先序遍历右孩子
		return result;
	}
}

node* AddNode(node* root,char* parent,char* lchild,char* rchild)//添加节点
{
	if(root == NULL)//若没有根节点 则首先为根节点分配空间并建立根节点
	{
		root = (node*)malloc(sizeof(node));
		strcpy(root->name,parent);
		root->lc=NULL;//暂时初始化左右孩子为NULL
		root->rc=NULL;
		strcpy(root->pname,'\0');
		root->generation=0;
	}

	node* temp=FindNode(root,parent);//在根节点为root的整棵树中,找到名字为parent的节点 并用指针temp指向该节点
	printf("%s\n",temp->name);

	node* lc=(node*)malloc(sizeof(node));//建立左孩子
	strcpy(lc->name,lchild);
	strcpy(lc->pname,parent);
	lc->generation = temp->generation+1;
	lc->lc=NULL;
	lc->rc=NULL;

	node* rc=(node*)malloc(sizeof(node));//建立右孩子
	strcpy(rc->name,rchild);
	strcpy(rc->pname,parent);
	rc->generation=temp->generation+1;
	rc->lc=NULL;
	rc->rc=NULL;

	temp->lc=lc;//连接左孩子
	temp->rc=rc;//连接右孩子
	return root;//返回根节点 相当于返回整棵树
}

void FindRelation(node* root,char* person1,char* person2)
{
	node*p1=FindNode(root,person1);//查找name为person1的节点
	node*p2=FindNode(root,person2);//查找name为person2的节点

	node* min;
	node* max;
	if(p1->generation>p2->generation)
	{
		min=p1;max=p2;
	}
	else
	{
		min=p2;max=p1;
	}

	int level=min->generation-max->generation;
	while(min->generation>max->generation)//找到同一辈分 就是将小辈分雨大辈分处于同一辈分上寻找共同祖先
	{
		char* parent=min->pname;
		min=FindNode(root,parent);
	}

	while(!IsSame(min->pname,max->pname))//如果此时不是共同祖先 就向上推一层再找共同祖先 直到找到共同祖先
	{
		char* parent=min->pname;
		min=FindNode(root,parent);
		parent=max->pname;
		max=FindNode(root,parent);
	}
	printf("%s %d\n",min->pname,level);
}


int main()
{
	node* root = NULL;//建立一个根节点指针
	char ch;
	int tag=0;//用于控制输入与输出
	char parent[NAME],lchild[NAME],rchild[NAME];//建立三个字符串分别用于输入父名 左子名 右子名
	while(tag=0 && (ch=getchar())!=EOF)
	{
		parent[0]=lchild[0]=rchild[0]='\0';//每次输入都初始化
		char str[3*NAME+2];
		int index=0;//index个字符

		ch=getchar();
		while(ch!='\n')//直到输入换行
		{		
			str[index++]=ch;
			ch=getchar();
		}
		str[index]='\0';
//		printf("%s\n",str);
		GetName(str,index,parent,lchild,rchild);//切分字符串
		printf("%s\t%s\t%s\n",parent,lchild,rchild);
		if(strlen(rchild))//0找关系 1添加
		{
			root = AddNode(root,parent,lchild,rchild);//输入三项 就添加节点  root相当于整颗树 它指向整棵树的根节点
		}
		else if(strlen(rchild)==0)//只输入2项 则找关系
		{
			FindRelation(root,parent,lchild);
			tag=1;
		}
	}

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值