PTA-7-3 树的同构

题目描述:

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

很惭愧,这个题目做的很复杂,但是思路很清晰,希望能分享出来,
思路和难点如下:

  1. 同构的树有一个特点,那就是每一层的结点都是一样的,有且仅出现一次。
    所以我们只需要使用层序遍历来进行比较就行了

  2. 我们需要读取树,而且需要确定树的根结点
    确定树的根结点的时候,我们可以使用一个布尔数组来记录
    没有成为过子结点的结点就是根结点

  3. 读取树的过程中,我们不能使用 scanf 直接读取,因为会读到空格和换行,我们可以使用 getchar() 来吃掉空格

所以我们按照以上思路完成代码如下:

/*
*  Author: Veeupup
*  树的同构
*/
#include <iostream>
#include <cstdio>
#include <cstdint>
#include <queue>
#include <cctype>
#include <vector>
#include <algorithm>
using namespace std;

struct Node
{
   char data;
   int left, right, layer;
} tree1[11], tree2[11]; // 两棵树分别保存左右两边的信息

bool cmp(Node a, Node b)
{
   return a.data < b.data;
}

int n1, n2;
int head1, head2;                      // 记录头结点
bool isRoot[11] = {true};              // 记录是否是头结点
vector<Node> layers1[15], layers2[15]; // 保存每层的结点
char tempData, tempLeft, tempRight;
string str;
queue<int> myQ;
int nowLayer;

int main()
{
   freopen("data.txt", "r", stdin);
   scanf("%d", &n1);
   getchar();
   if (n1 != 0)
   {
       for (int i = 0; i < n1; i++)
       { // 读取信息, 保存到当前的树中
           getline(cin, str);
           tempData = str[0];
           tempLeft = str[2];
           tempRight = str[4];
           tree1[i].data = tempData; // 记录当前的符号
           if (isdigit(tempLeft))
           {
               tree1[i].left = tempLeft - '0';
               isRoot[tempLeft - '0'] = false; // 成为过左子结点
           }
           else
           { // -1 代表该结点不存在
               tree1[i].left = -1;
           }
           if (isdigit(tempRight))
           {
               tree1[i].right = tempRight - '0';
               isRoot[tempRight - '0'] = false; // 成为过右子结点
           }
           else
           { // -1 代表不存在
               tree1[i].right = -1;
           }
       }
       for (int i = 0; i < n1; i++)
       {
           if (isRoot[i])
           {
               head1 = i;
               break;
           }
       }
       myQ.push(head1);
       nowLayer = 1;
       tree1[head1].layer = nowLayer;
       // 层序遍历
       int topId;
       while (!myQ.empty())
       {
           topId = myQ.front();
           nowLayer = tree1[topId].layer;
           layers1[nowLayer].push_back(tree1[topId]); // 记录每一层的数值
           myQ.pop();
           if (tree1[topId].left != -1)
           {
               int left = tree1[topId].left;
               tree1[left].layer = nowLayer + 1;
               myQ.push(left);
           }
           if (tree1[topId].right != -1)
           {
               int right = tree1[topId].right;
               tree1[right].layer = nowLayer + 1;
               myQ.push(right);
           }
       }
   }
   scanf("%d", &n2);
   getchar();
   if (n2 != 0)
   {

       fill(isRoot, isRoot + 11, true);
       for (int i = 0; i < n2; i++)
       {
           getline(cin, str);
           tempData = str[0];
           tempLeft = str[2];
           tempRight = str[4];
           tree2[i].data = tempData; // 记录当前的符号
           if (isdigit(tempLeft))
           {
               tree2[i].left = tempLeft - '0';
               isRoot[tempLeft - '0'] = false;
           }
           else
           { // -1 代表该结点不存在
               tree2[i].left = -1;
           }
           if (isdigit(tempRight))
           {
               tree2[i].right = tempRight - '0';
               isRoot[tempRight - '0'] = false;
           }
           else
           { // -1 代表不存在
               tree2[i].right = -1;
           }
       }
       for (int i = 0; i < n2; i++)
       {
           if (isRoot[i])
           {
               head2 = i;
               break;
           }
       }
       myQ.push(head2);
       nowLayer = 1;
       tree2[head2].layer = nowLayer;
       while (!myQ.empty())
       {
           int topId = myQ.front();
           nowLayer = tree2[topId].layer;
           myQ.pop();
           layers2[nowLayer].push_back(tree2[topId]); // 记录每一层的数值
           if (tree2[topId].left != -1)
           {
               int left = tree2[topId].left;
               tree2[left].layer = nowLayer + 1;
               myQ.push(left);
           }
           if (tree2[topId].right != -1)
           {
               int right = tree2[topId].right;
               tree2[right].layer = nowLayer + 1;
               myQ.push(right);
           }
       }
   }
   bool flag = true;
   for (int i = 0; i <= 11; i++)
   {
       if (layers1[i].size() != layers2[i].size())
       {
           flag = false;
           break;
       }
       else if (layers1[i].size() != 0)
       {
           // 当存在而且不为 0 时,比较两个集合中的数据是否都相同
           sort(layers1[i].begin(), layers1[i].end(), cmp);
           sort(layers2[i].begin(), layers2[i].end(), cmp);
           for (int j = 0; j < layers1[i].size(); j++)
           {
               if (layers1[i][j].data != layers2[i][j].data)
               {
                   flag = false;
                   break;
               }
           }
       }
   }
   if (!flag)
   {
       printf("No");
   }
   else 
   {
       printf("Yes");
   }
   return 0;
}
posted @ 2020-03-29 15:40  南风sa  阅读(270)  评论(0编辑  收藏  举报