1.在此之前,要先了解满二叉树,和完全二叉树的区别
- 满二叉树:在一棵二叉树中,只包含度为2和0的结点
- 完全二叉树:度可以包含为2,为1,为0的结点
满二叉树的除了树的根节点(或子树的根节点)剩下的都是2n(偶数),也就是左右子树的结点个数都相同。
2.废话不多说,直接进行讲解:
- 了解到了满二叉树的左右子树结点个数相同
- 例如:有一个先序序列:abcdefg,a肯定为根,在之后肯定是先把左子树遍历完,在去遍历右子树。在遍历左子树的时候,左子树也是一个树,还需将左子树拿出来查看左子树,按照先左后右先左后右的此规律,不难想到可以利用递归来解决。每次记录一次区间,标记当前树的开始和结束下标。因为在此区间内,也为一个完整的子树,所以每次肯定也要将此子树进行分割,前一半为左子树,后一半为右子树。
3.经过以上的逻辑,通过递归可以写出简洁代码
string post; // 用来记录后序序列
// 先序序列 开始下标 结束下标
void buildFromPre(string pre, int start, int end)
{
// 只有当区间的左端点<=右端点时,才可以进行分割子树,当等于时,就只有一个结点,也分割不来了
if(start<=end){
// 因为根据满二叉树的性质,左子树和右子树的结点个数是相同的,
// 而且根据先序,前一半为左子树,后一半为右子树
int half = (end - start)/2;
// 递归左子树(左半区间)[start+1, start+half] (都为闭区间)
buildFromPre(pre, start+1, start+half);
// 递归右子树(右半区间) [start+half+, end] (闭区间)
buildFromPre(pre, start+half+1, end);
// 因为求后序序列,则最后才加入字符串
post+=pre[start];
}
}
int main()
{
string pre = "abcdefg";
buildFromPre(pre, 0, pre.size()-1);
cout<<endl;
for(int i=0;i<pre.size();i++){
cout<<post[i];
}
cout<<endl;
}