PTA 数据结构与算法题目:是否同一棵二叉搜索树

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/abc15766228491/article/details/86290124

本题目为陈越、何钦铭老师的数据结构课后作业
7-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

下面方法,先建立一颗树,后面的需要和这棵树判断的树的所有节点都在这个树上查找进行并判断

#include <iostream>
#include <vector>
using namespace std;
struct point{
    int element;  // 节点元素
    int left, right;  // 节点左右儿子,均为在vector中的下标
    int flag;  // 标记是否遍历过
    int index;  // 该节点本身的下标
    point(int _element, int _left, int _right, int _flag, int _index):
    element(_element), left(_left), right(_right), flag(_flag), index(_index){}
};
vector<point> v_Tree;
int findFather(int root_index, int node){
    // 找这个节点的父亲节点,如果改该节点小于根节点的值且左儿子不空,则遍历左子树,如果左儿子空,则返回这个节点,右儿子类似
    if(v_Tree[root_index].left != -1 and node<v_Tree[root_index].element)
        return findFather(v_Tree[root_index].left, node);
    else if(v_Tree[root_index].left == -1 and node<v_Tree[root_index].element)
        return root_index;
    else if(v_Tree[root_index].right != -1 and node>v_Tree[root_index].element)
        return findFather(v_Tree[root_index].right, node);
    else if(v_Tree[root_index].right == -1 and node>v_Tree[root_index].element)
        return root_index;
}
void createTree(int num){
    int tree_element;
    cin>>tree_element;
    //  第一个值作为根,这里要先将v_Tree清除
    v_Tree.clear();
    v_Tree.emplace_back(point(tree_element, -1, -1, 0, 0));
    for (int i = 1; i < num; ++i) {
        cin>>tree_element;
        int father_node_index = findFather(0, tree_element);
        if(tree_element>v_Tree[father_node_index].element)
            v_Tree[father_node_index].right = i;
        else
            v_Tree[father_node_index].left = i;
        v_Tree.emplace_back(point(tree_element, -1, -1, 0, i));
    }
}
int findNode(int node){
    //  查找节点,如果在查找过程中发现经过了以前没有经过的节点(flag=0)则两个搜索树不相同
    int temp_index = v_Tree[0].index;
    while(true){
        if(node<v_Tree[temp_index].element){
            if(v_Tree[temp_index].flag==1 and v_Tree[temp_index].left != -1)  // 如果这个点走过了,并且左儿子存在,则遍历左子树
                temp_index = v_Tree[temp_index].left;
            else return 0;
        }
        else if(node>v_Tree[temp_index].element ){
            if(v_Tree[temp_index].flag==1 and v_Tree[temp_index].right != -1) 
                temp_index = v_Tree[temp_index].right;
            else return 0;
        }
        else {
            if(v_Tree[temp_index].flag == 1) return 0;
            else {
                v_Tree[temp_index].flag = 1;
                return 1;
            }
        }
    }
}
int judgeTree(int node_num)
{
    int node, flag = 1;
    for (int i = 0; i < node_num; ++i) {
        // 对输入的每个节点都查找,只要有一个节点返回false则后续的节点只输入不查找
        cin>>node;
        if(flag) flag = findNode(node);
    }
    return flag;
}
void clear_flag()
{
    // 在下一轮遍历中先清零
    for (auto item = v_Tree.begin(); item != v_Tree.end(); item++) {
        item->flag = 0;
    }
}
int main()
{
    int node_num;
    cin>>node_num;

    while(node_num){
        int tree_num;
        cin>>tree_num;
        //  第一行数据创建一棵树
        createTree(node_num);
        for(int i=0;i<tree_num;i++)
        {
            clear_flag();
            int result = judgeTree(node_num);
            if(result) cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
        }
        cin>>node_num;
    }
}

猜你喜欢

转载自blog.csdn.net/abc15766228491/article/details/86290124