【题目链接】
ybt 1368:对称二叉树(tree_c) 根据测试,可以认为输入的序列长度小于等于500
【题目考点】
1. 二叉树 顺序存储结构
- 第1结点为树的根结点
- 第i结点的左孩子编号为2i,右孩子编号为2i+1
- 第i结点的双亲结点编号为i/2(整除运算)。
设数组tree,tree[i] 表示第i结点的值。 适合存储满二叉树与完全二叉树
【解题思路】
题目给的输入的序列是二叉树的顺序存储结构, 设数组tree,tree[i] 表示用顺序存储结构保存二叉树第i结点的值。 那么输入的第i个字符就是tree[i] 的值。 这里可以使用每次循环读入一个字符的方法,当读入EOF时停止读入。也可以先读入整个字符串,再做赋值。为tree数组设值。 设标志位isSym表示该树是否是对称的。 遍历整棵树(使用哪种遍历方法都可以),看每个结点的左右孩子,如果左右孩子中有1个是空结点而另一个不是,那么整棵树就不是对称的。遍历完所有结点后,可以确定该树是否是对称的。 注意在遍历顺序存储结构的树的时候,临时求出的下标可能会很大(因为每次都会乘以2),所以数组尽量开得大一些(比如最后一个结点的地址是1000,那么要把数组长度开成2000多),也可以先记录整个顺序存储结构tree数组中最后一个元素的下标tn,如果访问到的下标超过tn,那么这次访问无意义,直接返回。
本题也可以使用链式存储结构完成。题目给定的顺序存储结构字符序列,实际就是树的带空结点的层次遍历序列。可以模拟层次遍历的过程来设置结点间的关系。
在遍历时,以先序遍历为例,如果使用递归的方法做遍历,那么需要把表示该树是否对称的量声明成全局变量。如果使用非递归的方法做遍历,就可以使用函数的返回值来表示该树是否对称,效率更高。
【题解代码】
解法1:顺序存储结构 递归
#include <bits/stdc++.h>
using namespace std;
#define N 1005
char tree[N];
int tn;
bool isSymmetric(int r)
{
if(tree[r] == '\0')
return true;
if(tree[2*r] == '\0' && tree[2*r+1] != '\0' ||
tree[2*r] != '\0' && tree[2*r+1] == '\0')
return false;
return isSymmetric(2*r) && isSymmetric(2*r+1);
}
int main()
{
char c;
while((c = cin.get()) != EOF)
{
if(c == '#' || c == '\n')
tree[++tn] = '\0';
else
tree[++tn] = c;
}
cout << (isSymmetric(1) ? "Yes" : "No");
return 0;
}
解法2:顺序存储结构 递归先序遍历
#include <bits/stdc++.h>
using namespace std;
#define N 105
char tree[N];
int tn;
bool isSym = true;
void preOrder(int r)
{
if(r > tn || tree[r] == '\0' || isSym == false)
return;
if(tree[2*r] == '\0' && tree[2*r+1] != '\0' ||
tree[2*r] != '\0' && tree[2*r+1] == '\0')
{
isSym = false;
return;
}
preOrder(2*r);
preOrder(2*r+1);
}
int main()
{
char c;
while((c = cin.get()) != EOF)
{
if(c == '#' || c == '\n')
tree[++tn] = '\0';
else
tree[++tn] = c;
}
preOrder(1);
cout << (isSym ? "Yes" : "No");
return 0;
}
解法3:链式存储结构 非递归先序遍历
#include <bits/stdc++.h>
using namespace std;
#define N 1005
struct Node
{
char val;
int left, right;
};
Node node[N];
int p;
string s;
int si;
int createTree()
{
char c;
queue<int> que;
int np = ++p, lp, rp;
node[np].val = s[si++];
que.push(np);
while(que.empty() == false)
{
int u = que.front();
que.pop();
c = s[si++];
if(c == '#' || si == s.length())
lp = 0;
else
{
lp = ++p;
node[lp].val = c;
}
c = s[si++];
if(c == '#' || si == s.length())
rp = 0;
else
{
rp = ++p;
node[rp].val = c;
}
node[u].left = lp;
node[u].right = rp;
if(si < s.length())
{
que.push(lp);
que.push(rp);
}
}
return np;
}
bool isSymmetric(int r)
{
stack<int> stk;
stk.push(r);
while(stk.empty() == false)
{
int u = stk.top();
stk.pop();
if(node[u].left == 0 && node[u].right != 0 ||
node[u].left != 0 && node[u].left == 0)
return false;
if(node[u].right != 0)
stk.push(node[u].right);
if(node[u].left != 0)
stk.push(node[u].left);
}
return true;
}
int main()
{
cin >> s;
int root = createTree();
cout << (isSymmetric(root) ? "Yes" : "No");
return 0;
}
|