035树的子结构(keep it up)

剑指offer中题目:http://ac.jobdu.com/problem.php?pid=1520

题目描述:

输入两颗二叉树A,B,判断B是不是A的子结构。

输入:

输入可能包含多个测试样例,输入以EOF结束。
对于每个测试案例,输入的第一行一个整数n,m(1<=n<=1000,1<=m<=1000):n代表将要输入的二叉树A的节点个数(节点从1开始计数),m代表将要输入的二叉树B的节点个数(节点从1开始计数)。接下来一行有n个数,每个数代表A树中第i个元素的数值,接下来有n行,第一个数Ki代表第i个节点的子孩子个数,接下来有Ki个树,代表节点i子孩子节点标号。接下来m+1行,与树A描述相同。

输出:

对应每个测试案例,
若B是A的子树输出”YES”(不包含引号)。否则,输出“NO”(不包含引号)。

样例输入:
7 3
8 8 7 9 2 4 7
2 2 3
2 4 5
0
0
2 6 7
0
0
8 9 2
2 2 3
0
0

1 1
2
0
3
0
样例输出:
YES
NO
提示:

B为空树时不是任何树的子树。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <queue>
 
#define MAXDATA 0X7FFFFFFF
#define MAXSIZE 1001
 
int TreeData[MAXSIZE];
 
typedef struct SNode
{
    int data;
    int left;
    int right;
}SNode;
 
SNode* createNode(int vData)
{
    SNode *Node = (SNode*)malloc(sizeof(SNode));
    Node->data  = vData;
    Node->left  = -1;
    Node->right = -1;
    return Node;
}
 
void deleteNode(SNode **vNode)
{
    (*vNode)->left  = -1;
    (*vNode)->right = -1;
    free(*vNode);
    *vNode = NULL;
}
 
void allocNode(SNode *vArray[], int vSize)
{
    int i;
    for (i = 1; i <= vSize; ++i)
    {
        vArray[i] = createNode(MAXDATA);
    }
}
 
void deleteTree(SNode *vTree[], int vSize)
{
    int i;
    for (i=1; i <= vSize; ++i)
    {
        deleteNode(&(vTree[i]));
    }
}
 
void clearTree(SNode *vTree[], int vSize)
{
    int i;
    for (i=1; i <= vSize; ++i)
    {
        vTree[i]->data  = MAXDATA;
        vTree[i]->left  = -1;
        vTree[i]->right = -1;
    }
}
 
void createBinaryTree(SNode *vNode[], int vN)
{
    int    i;
    int    NumChld;
 
    for (i = 1; i <= vN; ++i)
    {
        scanf("%d", &(vNode[i]->data));
    }
 
    for (i = 1; i <= vN; ++i)
    {
        scanf("%d", &NumChld);
        if (NumChld == 0) continue;
        else if (NumChld == 1)
        {
            scanf("%d", &(vNode[i]->left));
        }
        else if (NumChld == 2)
        {
            scanf("%d %d", &(vNode[i]->left), &(vNode[i]->right));
        }
    }
}
 
int judgeSubRoot(int vRootBegin, SNode *vTreeRoot[], int vSubBegin, SNode *vSubRoot[])
{
    int LeftFlag;
    int RightFlag;
     
    if (vSubBegin == -1)  return 1;
    if (vRootBegin == -1) return 0;
 
    if (vTreeRoot[vRootBegin]->data == vSubRoot[vSubBegin]->data) 
    {
        LeftFlag = judgeSubRoot(vTreeRoot[vRootBegin]->left, vTreeRoot, vSubRoot[vSubBegin]->left, vSubRoot);
        if (!LeftFlag) return 0;
        RightFlag = judgeSubRoot(vTreeRoot[vRootBegin]->right, vTreeRoot, vSubRoot[vSubBegin]->right, vSubRoot);
        if (!RightFlag) return 0;
        return 1;
    }
    else return 0;
}
 
int isSubTree(SNode *vTreeRoot[], SNode *vSubRoot[])
{
    if (vSubRoot[1]->data == MAXDATA || vTreeRoot[1]->data == MAXDATA) return 0;
 
    std::queue<int> Que;
    int Index;
    int Flag;
 
    Que.push(1);
    while(!Que.empty())
    {
        Index = Que.front();
        Que.pop();
 
        if (vTreeRoot[Index]->data == vSubRoot[1]->data)
        {
            Flag = judgeSubRoot(Index, vTreeRoot, 1, vSubRoot);
            if (Flag) return 1;
        }
 
        if (vTreeRoot[Index]->left != -1)  Que.push(vTreeRoot[Index]->left);
        if (vTreeRoot[Index]->right != -1) Que.push(vTreeRoot[Index]->right);
    }
 
    return 0;
}
 
int main()
{
    int M;
    int N;
    SNode *TreeRoot[MAXSIZE];
    SNode *SubRoot[MAXSIZE];
 
    allocNode(TreeRoot, MAXSIZE-1);
    allocNode(SubRoot, MAXSIZE-1);
 
    while (scanf("%d %d", &N, &M) != EOF)
    {
        createBinaryTree(TreeRoot, N);
        createBinaryTree(SubRoot, M);
 
        if (isSubTree(TreeRoot, SubRoot))
        {
            printf("YES\n");
        }
        else
        {
            printf("NO\n");
        }
 
        clearTree(TreeRoot, MAXSIZE-1);
        clearTree(SubRoot, MAXSIZE-1);
    }
 
    deleteTree(TreeRoot, MAXSIZE-1);
    deleteTree(SubRoot, MAXSIZE-1);
 
    return 0;
}
/**************************************************************
    Problem: 1520
    User: 
    Language: C++
    Result: Accepted
    Time:10 ms
    Memory:1056 kb
****************************************************************/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值