题目如下:
给出一棵二叉树的中序与后序排列。求出它的先序排列。(约定树结点用不同的大写字母表示,长度 ≤ 8)
题单链接:
(0条未读通知) 牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)
函数声明:
Tree* Recover(string *a, string b);
解题思路:
首先后序排列的最后一个字符为根节点,根据此节点找到先序序列中的节点位置,以此节点分割除左子树和右子树2个字符串。先将去掉最后一个字符的后续排列字符串的首地址和右子树的字符串为参数递归调用Recover函数。如果右子树为0则将根节点的右叶子节点置为nullptr;其次将去掉最后一个字符的后续排列字符串的首地址和左子树的字符串为参数递归调用Recover函数。如果左子树为0则将根节点的左叶子节点置为nullptr;最后返回根节点,进行先序遍历即可。
图解:
注意:字符串a必须传入首地址,否则a进入递归无法做到每次取出最后一个元素作为根节点,最后构建的二叉树会出现重复节点。
代码实现:
#include<iostream>
#include<string>
using namespace std;
struct Tree {
char data;
Tree* left;
Tree* right;
};
Tree* Creat(char a);
Tree* Recover(string *a, string b);
void DLR(Tree* root);
int main() {
string a;// = "BDCA";//后序序列
string b;// = "BADC";//中序序列
cin >> b;
cin >> a;
Tree* root = Recover(&a, b);
DLR(root);
return 0;
}
Tree* Creat(char a) {
Tree* root=new Tree;
root->data = a;
root->left = nullptr;
root->right = nullptr;
return root;
}
Tree* Recover(string *a, string b) {
int number = b.find(*(a->end()-1));
Tree* root = Creat(*(a->end()-1));
a->erase(a->end()-1);//去除最后一个元素
string pa;//左子树
string pb;//右子树
for (int i = 0; i < number; ++i) {
pa.push_back(b[i]);
}
for (int i = number+1; i < b.size(); ++i) {
pb.push_back(b[i]);
}
//cout << pa << " " << pb << endl;
if (pb.size() != 0) {
root->right = Recover(a, pb);
}
else {
root->right = nullptr;
}
if (pa.size() != 0) {
root->left = Recover(a, pa);
}
else {
root->left = nullptr;
}
return root;
}
void DLR(Tree* root) {
if (root != nullptr) {
cout << root->data;
DLR(root->left);
DLR(root->right);
}
}
希望我的思路能够帮助到你,如果你有更好的方法或者疑惑都可以留言评论区。