题目描述
给定一组森林,编写程序生成对应的二叉树,输出这颗二叉树叶结点对应的二进制编码.规定二叉树的左边由0表示,二叉树的右边由1表示。
输入
N B 表示N个树,每结点最多B个分支
第2行至第N+1行,每个树的先序遍历
输出
每行表示一个叶结点对应的二进制编码.
输入样例1
3 3
A B 0 0 0 C 0 0 0 D 0 0 0
E F 0 0 0 0 0
G H 0 0 0 I J 0 0 0 0 0 0
输出样例1
0 1 1
1 0
1 1 0 1 0
解题思路
![](https://img-blog.csdnimg.cn/img_convert/d9b33e483869af4b22d9db3cb2336b4b.png)
题目样例的示意图
关键步骤是建树,即如何把输入的普通树的先序遍历转换成一颗二叉树。我们知道,普通树转换成二叉树的思想其实很简单,就是结点的第1个孩子作为该结点的左孩子,其余的孩子作为这个孩子前一个兄弟的右孩子,即该结点的第i个孩子是第i-1个孩子的右孩子。而森林是由多棵树组成的,因此只需要分别将各课树先转换成二叉树之后,再将第i棵树的根结点作为第i-1棵树的根结点的右孩子。
思路很简单,代码上怎么实现呢?我的做法是递归建树:遇到非0字符新建结点,递归找到第一个孩子(注意:一个结点的孩子有可能先出现0再出现非0字符,所以不可以一找到0就断定它没有孩子,要全部找完都是0才是没有孩子!),之后其他孩子则作为前一个孩子的右孩子(一定要b个都找完!)。
森林转成二叉树后,编码也是递归实现,从根结点开始,左孩子存在则编码串加0继续递归,右孩子存在则编码串加1继续递归,遇到叶子结点就输出当前编码串。
C++代码
#include<iostream>
#include<string>
using namespace std;
struct Node //二叉树结点
{
char data;
Node* lchild;
Node* rchild;
};
Node* createBTree(string str, int& pos, int b)
{
Node* node = NULL;
if (pos < str.length() && str[pos] != '0')
{
node = new Node;
node->lchild = node->rchild = NULL; //初始化
node->data = str[pos];
pos = pos + 2; //跳过空格,到下一个字符
//第一个孩子为左孩子
int i = 0; //i记录当前轮到第几个孩子
while (!node->lchild && i < b) //左孩子为空则继续找
{
node->lchild = createBTree(str, pos, b);
i++;
}
//其他孩子为左孩子的右孩子
Node* temp = node->lchild;
for (; i < b; i++) //遍历完b个孩子
{
//不为0则是右孩子
if (str[pos] != '0')
{
temp->rchild = createBTree(str, pos, b);
temp = temp->rchild;
}
//等于0则跳向下一个字符
else
pos += 2;
}
}
else
pos += 2;
return node;
}
void coding(Node* node, string code)
{
//左子树存在则编码串加上0
if (node->lchild)
coding(node->lchild, code+"0");
//右子树存在则编码串加上1
if (node->rchild)
coding(node->rchild, code+"1");
//找到叶子结点则输出编码
if (!node->lchild && !node->rchild)
{
cout << code[0];
for (int i = 1; i < code.length(); i++)
cout << ' ' << code[i];
cout << endl;
}
}
int main()
{
int n, b; //n个树,每个结点最多b个分支
cin >> n >> b;
getchar();
//建树
string str[n];
Node* root[n]; //每棵树转化成的二叉树的根结点
//n棵树先各自转换成二叉树
for (int i = 0; i < n; i++)
{
getline(cin, str[i]);
int pos = 0;
root[i] = createBTree(str[i], pos, b);
}
//每一棵树的根结点的右孩子是后一棵树的根结点
for (int i = 0; i < n - 1; i++)
root[i]->rchild = root[i + 1];
//编码
coding(root[0], "");
return 0;
}