第三周
#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;
}
先求出前序遍历和中序遍历的序列,再递归遍历左子树、右子树、根,即可得到后序遍历序列。
#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;
}