ybt 1368:对称二叉树(tree_c)
根据测试,可以认为输入的序列长度小于等于500
tree[i]
表示第i结点的值。适合存储满二叉树与完全二叉树
题目给的输入的序列是二叉树的顺序存储结构,
设数组tree,tree[i]
表示用顺序存储结构保存二叉树第i结点的值。
那么输入的第i个字符就是tree[i]
的值。
这里可以使用每次循环读入一个字符的方法,当读入EOF时停止读入。也可以先读入整个字符串,再做赋值。为tree数组设值。
设标志位isSym表示该树是否是对称的。
遍历整棵树(使用哪种遍历方法都可以),看每个结点的左右孩子,如果左右孩子中有1个是空结点而另一个不是,那么整棵树就不是对称的。遍历完所有结点后,可以确定该树是否是对称的。
注意在遍历顺序存储结构的树的时候,临时求出的下标可能会很大(因为每次都会乘以2),所以数组尽量开得大一些(比如最后一个结点的地址是1000,那么要把数组长度开成2000多),也可以先记录整个顺序存储结构tree数组中最后一个元素的下标tn,如果访问到的下标超过tn,那么这次访问无意义,直接返回。
本题也可以使用链式存储结构完成。题目给定的顺序存储结构字符序列,实际就是树的带空结点的层次遍历序列。可以模拟层次遍历的过程来设置结点间的关系。
在遍历时,以先序遍历为例,如果使用递归的方法做遍历,那么需要把表示该树是否对称的量声明成全局变量。如果使用非递归的方法做遍历,就可以使用函数的返回值来表示该树是否对称,效率更高。
#include
using namespace std;
#define N 1005
char tree[N];//树的顺序存储结构,初值都为'\0',tree[i]:第i结点的值,如果为'\0'表示这里为空。
//tree[2*i]:第i结点的左孩子的值,tree[2*i+1]:第i结点右孩子的值
int tn;//tree数组最后一个元素的下标,应该保证N > 2*tn
bool isSymmetric(int r)//判断以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)//二叉树的顺序存储结构字符串读入tree
{
if(c == '#' || c == '\n')//遇到'#'或换行符,都转为0
tree[++tn] = '\0';
else
tree[++tn] = c;
}
cout << (isSymmetric(1) ? "Yes" : "No");
return 0;
}
#include
using namespace std;
#define N 105
char tree[N];//树的顺序存储结构,初值都为'\0',tree[i]:第i结点的值,如果为'\0'表示这里为空。
//tree[2*i]:第i结点的左孩子的值,tree[2*i+1]:第i结点右孩子的值
int tn;//tree数组最后一个元素的下标
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)//二叉树的顺序存储结构字符串读入tree
{
if(c == '#' || c == '\n')//遇到'#'或换行符,都转为0
tree[++tn] = '\0';
else
tree[++tn] = c;
}
preOrder(1);
cout << (isSym ? "Yes" : "No");
return 0;
}
#include
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++];//如果已经取到末尾,c为'#',否则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)//非递归先序遍历 判断以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;
}