题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的谦虚遍历和中序遍历的结果中都不含重复的数字。
#include <iostream>
#include <string>
using namespace std;
int find(const string &str, char c) //在字符串中查找字符的函数,参数是string类引用和字符
{
for (int i = 0; i < str.size(); ++ i)
if (c == str[i])
return i; //找到之后返回
return -1;
}
void PreMid(const string &pre, const string &mid) //参数是前序字符串引用和中序字符串引用
{
if (pre.size() == 0)
return ; //前序字符串为空
if(pre.size() != mid.size()) { //如果输入的序列长度不一样,那就无从谈重构
cout<<"error!!!"<<endl;
}
if(mid[0] == mid[mid.size()-1] && pre[0] == pre[pre.size()-1]){
if(pre[0] == mid[0]){
cout << pre; //输出叶子结点的值
return;
}
else{
cout<<"help1"<<endl;
throw std::exception("error1");
}
}
//根节点是第一个元素
int k = find(mid, pre[0]); //在中序中寻找前序的第一个字符(根节点)
if(k == -1){
cout<<"SOS"<<endl;
throw std::exception("error2");
}
//构造左子树
string pretmp = pre.substr(1, k); //第一个位置开始复制k个字符
string midtmp = mid.substr(0, k);
PreMid(pretmp, midtmp);
//构造右子树
pretmp = pre.substr(k + 1, pre.size() - k - 1);
midtmp = mid.substr(k + 1, mid.size() - k - 1);
PreMid(pretmp, midtmp);
//变成后序遍历要最后输出节点的值
cout << pre[0]; //输出非叶子结点的值
}
int main()
{
string pre, mid;
while (cin >> pre >> mid){
PreMid(pre, mid);
cout << endl;
}
return 0;
}
PS: 1.在终止条件判断是需要写成两个if语句,三个终止条件必须同时成立是才直接返回。如果pre[0] != mid[0]则两个序列无法重构二叉树,应该抛出异常。
2.三个条件都成立的话,则打印叶结点,并返回。
3.第二个抛出异常的地方也是无法重构二叉树的,在中序遍历中无法找到根结点。
4.这种方法是用字符串作为参数的,如果用整型数组呢?
5.basic_string substr(size_type _Off,size_type _Count) const;
功能:从一个字符串复制一个从指定位置开始,并具有指定长度的子字符串。
6.代码的健壮性需要注意。