一.递归

在A树中先序访问并比较结点,遇到与B树头结点值相等时,以A树当前结点为头结点再同时对A子树与B树先序访问并比较。
//先序遍历(递归)判断
#include <stdbool.h>
bool match(struct TreeNode* p1,struct TreeNode* p2){//用来判断后者是否为前者的子树
    if(!p2){//匹配树访问完毕,匹配成功
        return true;
    }
    if(!p1){//被匹配树已访问完毕,匹配树还有结点未访问,匹配失败
        return false;
    }
    if(p1->val!=p2->val){//当前结点不匹配,匹配失败
        return false;
    }
    //匹配当前结点左右子树,顺序为根->左->右
    return match(p1->left,p2->left) && match(p1->right,p2->right);
}
bool HasSubtree(struct TreeNode* pRoot1, struct TreeNode* pRoot2 ) {
    // write code here
    if(!pRoot1 || !pRoot2){
        return false;
    }
    bool flag=match(pRoot1,pRoot2);//判断当前的子树部分是否与B树匹配
    bool flag_left=HasSubtree(pRoot1->left,pRoot2);//判断左分支中是否有与B树匹配的子树
    bool flag_right=HasSubtree(pRoot1->right,pRoot2);//判断右分支中是否有与B树匹配的子树
    return flag || flag_left || flag_right;
}

二.利用辅助队列(纯C不推荐)

和先序遍历一样的思路,由于层次遍历不是基于递归,而是利用辅助队列储存结点值再访问。对比时需要用到3个辅助队列,有一定的空间开销。虽然逻辑好理解,但边界条件多,操作还复杂,特别是进出队操作加上了第二层的层次遍历,写完代码太浪费时间。
//层次遍历(辅助队列)判断
#include <stdbool.h>
bool HasSubtree(struct TreeNode* pRoot1, struct TreeNode* pRoot2 ) {
    // write code here
    if(!pRoot1 || !pRoot2){
        return false;
    }
    struct TreeNode *p1=pRoot1,*p2=pRoot2;
    //最后一个示例结点总数有29326个,超出了题目的数据范围
    int **p1_queue=(int**)malloc(15000*sizeof(int*));//存储A树结点地址
    int **p2_queue=(int**)malloc(15000*sizeof(int*));//存储B树结点地址
    int **temp=(int**)malloc(15000*sizeof(int*));//层次遍历A的子树的临时队列,用于储存子树结点地址
    int p1_top=-1,p1_rear=-1,p2_top=-1,p2_rear=-1;//定义队首,队尾指针
    p1_queue[++p1_rear]=pRoot1;
    p2_queue[++p2_rear]=pRoot2;
    while(p1_top!=p1_rear && p2_top!=p2_rear){//层次遍历,用数组存储访问过的值
        p1=p1_queue[++p1_top];
        p2=p2_queue[++p2_top];
        if(p1->val==p2->val){
            int temp_top=-1,temp_rear=-1;
            p2_top=-1;p2_rear=0;
            temp[++temp_rear]=p1;
            while(temp_top!=temp_rear && p2_top!=p2_rear){
                p1=temp[++temp_top];
                p2=p2_queue[++p2_top];
                if(p1->val==p2->val){
                    if(p1->left && p2->left){
                        temp[++temp_rear]=p1->left;
                        p2_queue[++p2_rear]=p2->left;
                    }
                    else if(!p1->left && p2->left){
                        p2_top=-1;p2_rear=0;
                        break;
                    }
                    if(p1->right && p2->right){
                        temp[++temp_rear]=p1->right;
                        p2_queue[++p2_rear]=p2->right;
                    }
                    else if(!p1->right && p2->right){
                        p2_top=-1;p2_rear=0;
                        break;
                    }
                }
                else{
                    p2_top=-1;p2_rear=0;
                    break;
                }
            }
            if(p2_top==p2_rear){
                return true;
            }
        }
        p2_top=-1;p2_rear=0;//重置对比进度
        p1=p1_queue[p1_top];
        if(p1->left){
            p1_queue[++p1_rear]=p1->left;
        }
        if(p1->right){
            p1_queue[++p1_rear]=p1->right;
        }
    }
    //free(p1_queue);free(p2_queue);free(temp);//NO FREE
    if(p2_top!=p2_rear){//若pRoot2树还有剩余则匹配失败
        return false;
    }
    return true;
}