您的位置:首页 > 其它

由中序与前序、中序与后序重建二叉树

2016-03-15 19:45 176 查看
由中序与前序、中序与后序重建二叉树

<span style="font-size:14px;">//节点类型
template<class T>
class TNode
{
public:
TNode() { lchild = rchild = parent = nullptr; };
T data;
TNode<T>* lchild, *rchild, *parent;
};</span>


一:已知前序与中序。

方法很简单,前序第一个节点为根节点,在中序中找到该节点。该位置左为左子树,右边为右子树。然后递归创建。
template<class T>
TNode<T>* TriTree<T>::MakeRootByPre(const string& Pre, const int PreBegin, const int PreEnd,
const string& In, const int InBegin, const int InEnd)
{
assert("" != Pre || "" == In);
if (!(PreBegin >= 0 && PreEnd >= 0 && InBegin >= 0 && InEnd >= 0))
{
return nullptr;
}
if (PreBegin > PreEnd || InBegin > InEnd ||
(unsigned)PreEnd >= Pre.length() || (unsigned)InEnd >= In.length())
{
return nullptr;
}
char ChRoot = Pre[PreBegin];
TNode<T>* pRoot = new TNode<T>();
//暂时不考虑父节点  并且遍历结果以字符串显示
pRoot->data = ChRoot;
int nPos = FindInString(In,ChRoot,InBegin,InEnd);
if (-1 == nPos)
{
return nullptr;
}
int CountOfLeftTree = nPos - InBegin;//左子树节点个数
pRoot->lchild = MakeRootByPre(Pre,PreBegin+1,PreBegin+ CountOfLeftTree,
In,InBegin,nPos-1);//递归创建左子树
pRoot->rchild = MakeRootByPre(Pre,PreBegin+CountOfLeftTree+1,PreEnd,
In,nPos+1,InEnd);
return pRoot;
}
二:由后序与中序重建,方法与一相似,有节点在后序遍历末尾而已。
template<class T>
TNode<T>* TriTree<T>::MakeRootByPost(const string& StrPost, const int PostBegin, const int PostEnd,
const string& StrIn, const int InBegin, const int InEnd)
{
//考虑父节点时可以再传一个参数即可
//也可以写一个重建函数连接父节点
assert(""!=StrPost&&""!=StrIn);
if (PostBegin < 0 || PostEnd < 0 || InBegin<0 || InEnd<0 ||
PostBegin>PostEnd || InBegin>InEnd||
PostEnd>=StrPost.length()||InEnd>=StrIn.length())
{
return nullptr;
}
TNode<T>* pRoot = new TNode<T>();
assert(nullptr!=pRoot);
char ChRoot = StrPost[PostEnd];
pRoot->data = ChRoot;
int nPos = FindInString(StrIn, ChRoot,InBegin,InEnd);
if (-1 == nPos)
{
return nullptr;
}
int CountOfLeftTree = nPos - InBegin;
pRoot->lchild = MakeRootByPost(StrPost,PostBegin,PostBegin+CountOfLeftTree-1,
StrIn,InBegin,nPos-1);//注意边界
pRoot->rchild = MakeRootByPost(StrPost,PostBegin+CountOfLeftTree,PostEnd-1,
StrIn,nPos+1,InEnd);
return pRoot;
}
思想都比较简单,个人认为代码写得比较清晰,大家可以看完代码,了解思想后,再手撸一遍。

template<class T>
int TriTree<T>::FindInString(const string& In, const char ChRoot, const int nBegin, const int nEnd)
{
//参数为闭区间
assert("" != In);
if (!(nBegin >= 0 && nEnd >=0 && nEnd >= nBegin&&nEnd < (int)In.length()))
{
return -1;
}
for (int i = nBegin; i <= nEnd; ++i)
{
if (ChRoot == In[i])
{
return i;
}
}
return -1;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: