叉树同构代码示例(C语言)

二叉树同构问题

题目

给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。
现给定两棵树,请你判断他们是否是同构的。

例如:
同构的树:
同构的两棵树

不是同构的树:
不是同构的两棵树

输入

输入格式:输入两棵二叉树的信息

  1. 先在一行中给出该树的结点数N;
  2. 输入N行,第i行对应编号第i个结点,给出该结点中存储的字母、其左孩子结点的编号、右孩子结点的编号;(结点可以按照任意顺序排列)
  3. 如果孩子结点为空,则在相应位置上给出"-"。

输入样例
输入样例
分别对应的二叉树:
第一棵树

第二棵树

求解思路

二叉树的表示

本题用结构数组表示二叉树(静态链表)

#define MAXSIZE 20
#define ElementType char
#define Tree int
#define bool int
#define Null -1//注意不是NULL

//定义两个静态链表T1、T2,未赋值
struct TreeNode
{
    ElementType Element;
    Tree Left;
    Tree Right;
}T1[MAXSIZE],T2[MAXSIZE];

Element存储结点信息;Left存储左儿子在数组中位置的下标;Right储存右儿子在数组中位置的下标(-1表示没有儿子)。

例如:
静态链表

程序框架

int main(void)
{
    建二叉树1;
    建二叉树2;
    判断是否同构并输出;

    return 0;
}

需要设计的函数

  1. 读数据建二叉树:Tree BuildTree(struct TreeNode [])
  2. 二叉树同构判别:bool Isomorphic(Tree, Tree)

所以程序框架:

int main(void)
{
    Tree R1 = 0, R2 = 0;

    R1 = BuildTree(T1);//读入输入的数据,并建立静态链表R1
    R2 = BuildTree(T2);//读入输入的数据,并建立静态链表R2

    //判断是否同构,同构打印Yes,否则打印No
    if (Isomorphic(R1, R2))
    {
        printf("Yes\n");
    }
    else
    {
        printf("No\n");
    }

    system("pause");
    return 0;
}

如何建立二叉树

主要难点在于找出二叉树的根结点

根结点与其他结点的区别在于没有父结点,所以记录结构数组中每个元素的左右子树指向的位置,最后始终没有被指中的就是根结点。
详细见代码中check[]数组。

如何判断两二叉树是否同构

运用递归的思路,将二叉树一步步分解成最小的树。
详细见代码中Isomorphic(R1, R2)函数。

代码示例

main.c文件

#include<stdio.h>
#include<stdlib.h>
#include"check.h"

int main(void)
{
    Tree R1 = 0, R2 = 0;

    R1 = BuildTree(T1);//读入输入的数据,并建立静态链表R1
    R2 = BuildTree(T2);//读入输入的数据,并建立静态链表R2

    //判断是否同构,同构打印Yes,否则打印No
    if (Isomorphic(R1, R2))
    {
        printf("Yes\n");
    }
    else
    {
        printf("No\n");
    }

    system("pause");
    return 0;
}

check.h文件

#define MAXSIZE 20
#define ElementType char
#define Tree int 
#define bool int
#define Null -1//注意不是NULL

//定义两个静态链表T1、T2,未赋值
struct TreeNode
{
    ElementType Element;
    Tree Left;
    Tree Right;
}T1[MAXSIZE],T2[MAXSIZE];

Tree BuildTree(struct TreeNode []);
bool Isomorphic(Tree, Tree);

BuildTree.c文件

#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<stdlib.h>
#include"check.h"


Tree BuildTree(struct TreeNode T[])
{
    int N = 0, Root = Null;
    int i = 0;
    char cl, cr;
    int *check = NULL;

    scanf("%d", &N);//读入结点数
    getchar();//吃掉缓冲区的回车
    if (N)
    {
        //check[]数组用于标记哪个结点没有父结点,没有的就是二叉树的根,全部初始化为0
        check = (int *)malloc(sizeof(int)*N);
        for (i = 0; i < N; i++)
        {
            check[i] = 0;
        }

        //读入输入的结点信息并加以处理
        for (i = 0; i < N; i++)
        {
            scanf("%c %c %c", &T[i].Element, &cl, &cr);
            getchar();//吃掉缓冲区的回车
            //将字符cl转化为数字,并标记有父结点的结点,对应的check[i]=1
            if (cl != '-')
            {
                T[i].Left = cl - '0';
                check[T[i].Left] = 1;
            }
            else
            {
                T[i].Left = Null;
            }
            //将字符cr转化为数字,并标记有父结点的结点,对应的check[i]=1
            if (cr != '-')
            {
                T[i].Right = cr - '0';
                check[T[i].Right] = 1;
            }
            else
            {
                T[i].Right = Null;
            }
        }

        //找出check[]数组中为0(没有父结点的结点)的位置,此位置就是根在数组T[]中的位置
        for (i = 0; i < N; i++)
        {
            if (check[i] == 0)
            {
                break;
            }
        }
        Root = i;
    }

    free(check);//释放空间

    return Root;
}

Isomorphic.c文件

#include<stdio.h>
#include<stdlib.h>
#include"check.h"

bool Isomorphic(Tree R1, Tree R2)
{
    //两棵二叉树都是空树的情况
    if (R1 == Null && R2 == Null)
    {
        return 1;
    }
    //两棵二叉树一个是空树,另一个不是的情况
    else if ((R1 == Null && R2 != Null) || (R1 != Null && R2 == Null))
    {
        return 0;
    }
    //根结点不一样的情况
    else if (T1[R1].Element != T2[R2].Element)
    {
        return 0;
    }
    //当 树1的左子树与树2的左子树同构 并且 树1的右子树与树2的右子树同构   或者   树1的左子树与树2的右子树同构 并且 树1的右子树与树2的左子树同构时,才算是同构
    else
    {
        return ((Isomorphic(T1[R1].Left, T2[R2].Left) && Isomorphic(T1[R1].Right, T2[R2].Right)) || (Isomorphic(T1[R1].Left, T2[R2].Right) && Isomorphic(T1[R1].Right, T2[R2].Left)));
    }
}
发布了12 篇原创文章 · 获赞 2 · 访问量 788

猜你喜欢

转载自blog.csdn.net/qq_42313728/article/details/100165889
今日推荐