• PTA 03-树1 树的同构 (25分)


    题目地址

    https://pta.patest.cn/pta/test/15/exam/4/question/711

    5-3 树的同构   (25分)

    给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。


    图1

    图2

    现给定两棵树,请你判断它们是否是同构的。

    输入格式:

    输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数NN (le 1010),即该树的结点数(此时假设结点从0到N-1N1编号);随后NN行,第ii行对应编号第ii个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出“-”。给出的数据间用一个空格分隔。注意:题目保证每个结点中存储的字母是不同的。

    输出格式:

    如果两棵树是同构的,输出“Yes”,否则输出“No”。

    输入样例1(对应图1):

    8
    A 1 2
    B 3 4
    C 5 -
    D - -
    E 6 -
    G 7 -
    F - -
    H - -
    8
    G - 4
    B 7 6
    F - -
    A 5 1
    H - -
    C 0 -
    D - -
    E 2 -
    

    输出样例1:

    Yes
    

    输入样例2(对应图2):

    8
    B 5 7
    F - -
    A 0 3
    C 6 -
    H - -
    D - -
    G 4 -
    E 1 -
    8
    D 6 -
    B 5 -
    E - -
    H - -
    C 0 2
    G - 3
    F - -
    A 1 4
    

    输出样例2:

    No


    /*
    评测结果
    时间	结果	得分	题目	编译器	用时(ms)	内存(MB)	用户
    2017-07-08 15:57	答案正确	25	5-3	gcc	14	1	
    测试点结果
    测试点	结果	得分/满分	用时(ms)	内存(MB)
    测试点1	答案正确	7/7	14	1
    测试点2	答案正确	7/7	2	1
    测试点3	答案正确	3/3	2	1
    测试点4	答案正确	2/2	1	1
    测试点5	答案正确	3/3	2	1
    测试点6	答案正确	3/3	10	1
    */
    #include <stdio.h>
    #include <stdlib.h>
    #define MAXLEN 10
    
    /*
    思路
    跟视频教程中的从根向下遍历来判断同构不同,本算法从叶子节点向上搜索。
    因为树是静态建立的,所以父节点比较容易记录。 
    */
    struct treenode{//创建节点结构体 
    	int data;	//存放内容 
    	int father; //存放父节点位置 
    	int lc;		//左儿子 
    	int rc;		//右儿子 
    	int isleaf; //是否为叶节点 
    };
    
    typedef struct tree{//树结构体 
    	struct treenode nodes[MAXLEN];//节点单元 
    	int len;//节点数量 
    	int root;//根节点位置 
    }* ptrTree;
    
    ptrTree CreateTree()//建树 
    {	
    	int i;
    	ptrTree T;
    	T=(ptrTree)malloc(sizeof(struct tree));
    	for(i=0;i<MAXLEN;i++)
    		T->nodes[i].father=-1; //提前将每个节点的父节点都初始化为-1 
    	return T;
    }
    
    void DestoryTree(ptrTree T) //释放空间 
    {
    	free(T);
    }
    
    void input(ptrTree T) //读入树 
    {
    	int i,length;
    	scanf("%d",&length);
    //	printf("%d,line40
    ",length);//test
    	T->len=length;
    	getchar();//skip a space
    	for(i=0;i<length;i++)
    	{
    	T->nodes[i].data=getchar();
    		getchar();//skip a space
    	T->nodes[i].lc=getchar();
    		getchar();//skip a space
    	T->nodes[i].rc=getchar();
    		getchar();//skip a space
    		
    	T->nodes[i].lc-='0';
    	T->nodes[i].rc-='0';
    
    //	printf("line58
    ");//test
    //	printf("#%d data=%c L=%d R=%d Father=%d leaf=%d
    ",i,T->nodes[i].data,T->nodes[i].lc,T->nodes[i].rc,T->nodes[i].father,T->nodes[i].isleaf);//test 
    
    	if(T->nodes[i].lc>=0)//如果一个节点有孩子,将此节点标记为孩子的父节点 
    		T->nodes[T->nodes[i].lc].father=i;
    	if(T->nodes[i].rc>=0)
    		T->nodes[T->nodes[i].rc].father=i;
    	if(T->nodes[i].lc<0 && T->nodes[i].rc<0)//如果一个节点没有孩子,那么此节点为叶节点 
    		T->nodes[i].isleaf=1;
    		
    //		printf("#%d data=%c L=%d R=%d Father=%d leaf=%d
    ",i,T->nodes[i].data,T->nodes[i].lc,T->nodes[i].rc,T->nodes[i].father,T->nodes[i].isleaf);//test 
    	}
    
    	for(i=0;i<length;i++){//遍历整棵树,父节点为-1的节点即为根。不过次算法后来也没用上这个量,留着不删了。 
    		if(T->nodes[i].father<0){
    			T->root=i;
    			break;
    		}
    	}
    }
    void printTree(ptrTree T)//测试用函数,输出树,看是否正确 
    {
    	int i;
    	printf("Tree.len=%d root=%d
     ",T->len,T->root);
    	for(i=0;i<T->len;i++){
    		printf("#%d %c L=%d R=%d Father=%d leaf=%d
    ",i,T->nodes[i].data,T->nodes[i].lc,T->nodes[i].rc,T->nodes[i].father,T->nodes[i].isleaf);
    	}
    }
    
    int CheckPath(ptrTree T1,ptrTree T2,int idx,int otheridx)//测试以下标idx的节点为起点,搜索另一棵树上的data相同的节点,若这二者的父节点值也相同,那么递归搜索到根为止。如不相同,则返回0; 
    {
    	int i,t1f,t2f;
    	t1f=T1->nodes[idx].father;
    	if(otheridx<0){//T2对应的下标值如果已知,那么不用再搜一遍了 
    		for(i=0;i<T1->len;i++)
    		if(T1->nodes[idx].data==T2->nodes[i].data)
    			break;
    		t2f=T2->nodes[i].father;
    	}else
    		t2f=T2->nodes[otheridx].father;
    	
    	if(( t1f<0 && t2f>=0) || (t1f>=0 && t2f<0)) return 0;
    	if (T1->nodes[t1f].data==T2->nodes[t2f].data){
    		if(T1->nodes[t1f].father<0)
    			return 1;
    		else return CheckPath(T1,T2,t1f,t2f);
    	}
    	else return 0;
    			
    }
    int Judge(ptrTree T1,ptrTree T2)
    {
    	int i,flag=1;
    	if(T1->len!=T2->len)//两棵树若节点数不同直接跳出 
    		return 0;
    	
    	if(T1->len==0){//两棵树都是空树,那么肯定算同构 
    		return 1;
    	}
    	if(T1->len==1){//若两棵树都只有一个节点,那么比较节点的值是否相同即可 
    		if(T1->nodes[0].data==T2->nodes[0].data)
    			return 1;
    		else return 0;
    	}
    	for(i=0;i<T1->len;i++){
    		if(T1->nodes[i].isleaf==1)	{//搜寻所有的叶子节点,搜索向上的路径。如果两棵树所有叶子节点的向上路径都相同,那么这两棵树同构 
    			flag=CheckPath(T1,T2,i,-1);//因为不知道第二棵树对应该叶子的index,所以填-1让它自己搜 
    			if(flag==0) return 0;
    		}
    	}
    	return 1;//循环期间没出过差错,那么可以return 1了 
    }	
    int main()
    {
    	int i;
    	ptrTree T1,T2;
    	T1=CreateTree();
    	T2=CreateTree();
    	input(T1);
    	input(T2);
    //	printTree(T1);//test 
    //	printTree(T2);//test
    	i=Judge(T1,T2);
    	if(i==1) printf("Yes");
    	else printf("No");
    }
    

      

  • 相关阅读:
    JVM内存模型
    生产者与消费者的Java实现
    kafka常用命令
    java中join用法
    elasticsearch关于索引切分的实现
    三十六进制加法
    leetCode之Median of Two Sorted Arrays
    腾讯云“动态加速”与“CDN”的区别——浅谈对“动态加速”的理解(可能有误)
    洗澡或游泳等导致的耳朵进水的解决方案
    windows服务器间文件同步搭建步骤搜集
  • 原文地址:https://www.cnblogs.com/gk2017/p/7140536.html
Copyright © 2020-2023  润新知