PTA浙江大学数据结构习题——第三周

第三周

树的同构

#include <iostream>
#include <cstring>

using namespace std;

const int N = 15;

struct TreeNode
{
    
    
    char e;
    int left, right;
} T1[N], T2[N];

bool st[N];

int BuildTree(struct TreeNode t[])
{
    
    
    int n;
    cin >> n;
    memset(st, false, sizeof st);
    
    char a, b, c;
    for (int i = 0; i < n; i ++)
    {
    
    
        cin >> a >> b >> c;
        t[i].e = a;
        if (b != '-')
        {
    
    
            t[i].left = b - '0';
            st[b - '0'] = true;
        }
        else    t[i].left = -1;
        
        if (c != '-')   
        {
    
    
            t[i].right = c - '0';
            st[c - '0'] = true;
        }
        else    t[i].right = -1;
    }
    
    // 寻根
    int root = -1;
    for (int i = 0; i < n; i ++)
        if (!st[i])
        {
    
    
            root = i;
            break;
        }
    return root;
}

bool check(int r1, int r2)
{
    
    
    if ((r1 == -1) && (r2 == -1))   return true;    // 两个节点为空
    
    if (((r1 == -1) && (r2 != -1)) || ((r1 != -1) && (r2 == -1)))   return false;   // 一个节点空,另一个不空
    if (T1[r1].e != T2[r2].e)   return false;       // 两个节点不相同
    
    if ((T1[r1].left == -1) && (T2[r2].left == -1)) return check(T1[r1].right, T2[r2].right);   // 两个节点的左子树都为空
    
    if ((T1[r1].left != -1) && (T2[r2].left != -1) && (T1[T1[r1].left].e == T2[T2[r2].left].e)) // 两个节点的左子树相同
        return check(T1[r1].left, T2[r2].left) && check(T1[r1].right, T2[r2].right);
    else    return check(T1[r1].left, T2[r2].right) && check(T1[r1].right, T2[r2].left);        // 检查两个节点的左右子树是否交换过
}

int main()
{
    
    
    int r1, r2;     // 两棵树的根节点
    r1 = BuildTree(T1), r2 = BuildTree(T2);
    
    if (check(r1, r2))  puts("Yes");
    else    puts("No");
    
    return 0;
}

树2 List Leaves
构建树的方法和上一题一样,层次遍历用队列实现。

#include <iostream>
#include <queue>

using namespace std;

const int N = 15;

struct TreeNode
{
    
    
    int x;
    int left, right;
} T[N];
bool st[N];

int buildTree(int n)
{
    
    
    for (int i = 0; i < n; i ++)
    {
    
    
        T[i].x = i;
        char a, b;
        cin >> a >> b;
        if (a != '-')
        {
    
    
            T[i].left = a - '0';
            st[a - '0'] = true;
        }
        else    T[i].left = -1;
        if (b != '-')
        {
    
    
            T[i].right = b - '0';
            st[b - '0'] = true;
        }
        else    T[i].right = -1;
    }
    int root = -1;
    for (int i = 0; i < n; i ++)
        if (!st[i])
        {
    
    
            root = i;
            return root;
        }
    return root;
}

int main()
{
    
    
    int n;
    cin >> n;
    int root = buildTree(n);
    
    vector<int> res;
    queue<struct TreeNode> q;
    q.push(T[root]);
    while (q.size())
    {
    
    
        auto p = q.front();
        q.pop();
        if (p.left == -1 && p.right == -1)  res.push_back(p.x);
        else
        {
    
    
            if (p.left != -1)   q.push(T[p.left]);
            if (p.right != -1)  q.push(T[p.right]);
        }
    }
    
    for (int i = 0; i < res.size() - 1; i ++)   cout << res[i] << " ";
    cout << res[res.size() - 1];
    
    return 0;
}

树3 Tree Traversals Again

先求出前序遍历和中序遍历的序列,再递归遍历左子树、右子树、根,即可得到后序遍历序列。

#include <iostream>
#include <vector>

using namespace std;

const int N = 35;

int n;
int in[N], pre[N];  // pre前序序列,in中序序列
int stk[N];         // 模拟1个栈
vector<int> res;

// 记录前序遍历和中序遍历的节点
void input()
{
    
    
    int top = -1, pre_idx = 0, in_idx = 0;
    string s;
    int x;
    for (int i = 0; i < n * 2; i ++)
    {
    
    
        cin >> s;
        if (s == "Push")
        {
    
    
            cin >> x;
            pre[pre_idx ++] = x;
            stk[++ top] = x;
        }
        else if (s == "Pop")
        {
    
    
            in[in_idx ++] = stk[top --];
        }
    }
}

void post(int pre_idx, int in_idx, int len)
{
    
    
    if (len == 0)   return;
    
    // 输出当前节点
    if (len == 1)
    {
    
    
        res.push_back(pre[pre_idx]);
        return;
    }
    
    int root = pre[pre_idx];            // 当前子树根节点
    int l_len, r_len;
    for (int i = 0; i < len + len; i ++)
        if (in[in_idx + i] == root)
        {
    
    
            l_len = i;                  // 左子树节点个数
            break;
        }
    r_len = len - l_len - 1;            // 右子树节点个数
    
    post(pre_idx + 1, in_idx, l_len);   // 输出左子树节点
    post(pre_idx + l_len + 1, in_idx + l_len + 1, r_len);   // 输出右子树节点
    res.push_back(root);
}

int main()
{
    
    
    cin >> n;
    input();
    post(0, 0, n);
    for (int i = 0; i < n - 1; i ++)    cout << res[i] << " ";
    cout << res[n - 1];

    return 0;
}

猜你喜欢

转载自blog.csdn.net/ManiacLook/article/details/124071012