04-树4 是否同一棵二叉搜索树 (25分)

题目描述

给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树,都得到一样的结果。于是对于输入的各种插入序列,你需要判断它们是否能生成一样的二叉搜索树。

输入格式

输入包含若干组测试数据。每组数据的第1行给出两个正整数N (≤10)和L,分别是每个序列插入元素的个数和需要检查的序列个数。第2行给出N个以空格分隔的正整数,作为初始插入序列。最后L行,每行给出N个插入的元素,属于L个需要检查的序列。
简单起见,我们保证每个插入序列都是1到N的一个排列。当读到N为0时,标志输入结束,这组数据不要处理。

输出格式

对每一组需要检查的序列,如果其生成的二叉搜索树跟对应的初始序列生成的一样,输出“Yes”,否则输出“No”。

输入样例

4 2
3 1 4 2
3 4 1 2
3 2 4 1
2 1
2 1
1 2
0

输出样例

Yes
No
No

解题思路

对于每一波(输入样例有两波),先将N和L读进来,然后根据第一个序列构建二叉搜索树,最后将接下来的序列与该树做比较,判断是否是同一棵二叉搜索树。那么现在主要有两个问题,一个是通过序列构建二叉搜索树,另一个是将序列与已有的树做比较。对于第一个问题,先把第一个值作为根,然后读取后面的值。若待插入的值比当前结点的值小,则插入在左子树上;若待插入的值比当前结点的值大,则插入在右子树上,显然这可以通过一个递归函数实现。对于第二个问题,可以在树的结点中添加一个标志,当标志为1时代表该结点已经比较过了,当标志为0时代表该结点还没比较过。因此每读取一个值的时候就调用一次比较函数。该函数从根节点开始比较,在当前结点标志为0的情况下,若结点值等于读取值,则说明比较成功,否则比较失败;在当前结点标志为1的情况下,若读取值大于结点值则比较结点的右子树,若读取值小于结点值则比较结点的左子树,若相等则比较失败(因为结点值唯一),显然这也可以通过一个递归函数实现。

代码

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

struct TreeNode {
    int data;
    int flag;
    struct TreeNode *left;
    struct TreeNode *right;
};
typedef struct TreeNode *Tree;

Tree makeTree(int n);
Tree newNode(int data);
Tree insert(Tree root, int data);
int judge(Tree root, int n);
int check(Tree root, int data);
void reset(Tree root);
void freeTree(Tree root);

int main() {
    int N, L;
    Tree root;
    scanf("%d", &N);
    while (N) {
        scanf("%d", &L);
        root = makeTree(N);
        for (int i = 0; i < L; i++) {
            if (judge(root, N)) printf("Yes\n");
            else printf("No\n");
            reset(root);
        }
        freeTree(root);
        scanf("%d", &N);
    }
    return 0;
}

Tree makeTree(int n) {
    Tree root;
    int data;
    scanf("%d", &data);
    root = newNode(data);
    for (int i = 1; i < n; i++) {
        scanf("%d", &data);
        root = insert(root, data);
    }
    return root;
}

Tree newNode(int data) {
    Tree node = (Tree) malloc(sizeof(struct TreeNode));
    node->data = data; node->flag = 0;
    node->left = NULL; node->right = NULL;
    return node;
}

Tree insert(Tree root, int data) {
    if (!root) {
        root = newNode(data);
    } else if (data > root->data) {
        root->right = insert(root->right, data);
    } else if (data < root->data) {
        root->left = insert(root->left, data);
    }
    return root;
}

int judge(Tree root, int n) {
    int data, flag = 0;
    scanf("%d", &data);
    if (root->data != data) flag = 1;
    else root->flag = 1;
    for (int i = 1; i < n; i++) {
        scanf("%d", &data);
        if (!flag && !check(root, data)) flag = 1;
    }
    if (flag) return 0;
    else return 1;
}

int check(Tree root, int data) {
    if (root->flag) {
        if (data > root->data) {
            return check(root->right, data);
        } else if (data < root->data) {
            return check(root->left, data);
        } else {
            return 0;
        }
    } else {
        if (data == root->data) {
            root->flag = 1;
            return 1;
        } else {
            return 0;
        }
    }
}

void reset(Tree root) {
    if (root->left) reset(root->left);
    if (root->right) reset(root->right);
    root->flag = 0;
}

void freeTree(Tree root) {
    if (root->left) freeTree(root->left);
    if (root->right) freeTree(root->right);
    free(root);
}
posted @ 2020-03-22 16:40  AndyHY  阅读(280)  评论(0编辑  收藏  举报