二叉树的前序中序后序遍历相互求法

  二叉树的前中后序遍历,他们的递归非递归。还有广度遍历,参见二叉树的前中后序遍历迭代&广度遍历二叉树的前中后序遍历简单的递归

  现在记录已知二叉树的前序中序后序遍历的两个,求另外一个。一般,这两个中一定有中序遍历。

  1、已知前序和中序,求后序遍历:

前序:ABDECFG  中序:DBEAFCG

思路简单:前序的第一个节点就是根节点,

     中序中找到根节点的位置,根节点之前是其左子树,之后是右子树

       按此顺序,依次在左子树部分遍历,右子树部分遍历

C++ 代码:

TreeNode *BinaryTreeFormorderings(char *Preorder, char *Inorder, int len)
{
       if(len == 0)
             return NULL;
       TreeNode *node=new TreeNode;
       node->val=*Preorder;
       int rootIndex=0;
       while(rootIndex<len)
       {
              if(Inorder[rootIndex] == *Preorder)
                      break; 
              ++rootIndex;
        }      
       node->left = BinaryTreeFormorderings(Preorder+1, Inorder, rootIndex);
       node->right = BinaryTreeFormorderings(Preorder+rootIndex+1,Inorder+rootIndex+1,len-(rootIndex+1));
       cout<<node->val;
       return node;    
}  

 注:上述代码,其实是在遍历的过程中建立了一个二叉树并返回,这是最全的。如果只是要个后续遍历的序列,可以在输出哪里以一个vector来存放序列就可以了,没必要建立二叉树的。如果只是要输出后续遍历,则在最后哪里输出就可以了,也没必要保存这个vector了。

 2、已知后和中序,求前序遍历:类似上述求后序的情况

后序:DEBFGCA 中序:DBEAFCG

思路简单:后序的最后一个节点就是根节点,

     中序中找到根节点的位置,根节点之前是其左子树,之后是右子树

      按此顺序,依次在左子树部分遍历,右子树部分遍历

C++代码:

TreeNode *BinaryTreePostorderings(char *Postorder, char *Inorder, int len)
{
    if (len == 0)
        return NULL;
    TreeNode *node = new TreeNode;
    node->val = *(Postorder + len - 1);
    cout << node->val;
    int rootIndex = 0;
    while (rootIndex<len)
    {
        if (Inorder[rootIndex] == *(Postorder + len - 1))
            break;
        ++rootIndex;
    }
    node->left = BinaryTreePostorderings(Postorder, Inorder, rootIndex);
    node->right = BinaryTreePostorderings(Postorder + rootIndex, Inorder + rootIndex + 1, len - (rootIndex + 1));
    return node;
}

 

  注:上述代码,与前文情况一致,根据具体情况需要来完成前序的遍历。

又写了一次遍历方式,用vector存放数据,起点终点,函数参数传入:

 

void BinaryTree::PreIn_to_post(std::vector<int> &pre, int first, int end, std::vector<int> &in, int first2, int end2, std::vector<int> &post)
{                 
    if (pre.size() == 0 || in.size() == 0 || first<0 || end>pre.size()-1 || first2<0 || end2>in.size()-1 ||first>end || first2>end2 || end-first != end2-first2)
        return;
    if (first == end)
    {
        post.push_back(pre[first]);
        return;
    }
    int index2 = first2;
    while (index2 <= end2 && in[index2] != pre[first])
        ++index2;
    PreIn_to_post(pre, first + 1, first+index2-first2, in, first2, index2-1, post);
    PreIn_to_post(pre, first+ 1+index2 -first2, end, in, index2 + 1, end2, post);
    post.push_back(pre[first]);
}


void BinaryTree::PostIn_to_pre(std::vector<int> &post, int first, int end, std::vector<int> &in, int first2, int end2, std::vector<int> &pre)
{
    if (post.size() == 0 || in.size() == 0 || first<0 || end>post.size() - 1 || first2<0 || end2>in.size() - 1 || first > end || first2 > end2 || end - first != end2 - first2)
        return;
    if (first == end)
    {
        pre.push_back(post[end]);
        return;
    }
    int index2 = first2;
    while (index2 <= end2&&in[index2] != post[end])
        ++index2;
    pre.push_back(post[end]);
    PostIn_to_pre(post, first, first + (index2 - first2)-1, in, first2, index2 - 1, pre);
    PostIn_to_pre(post, first + index2 - first2, end - 1, in, index2 + 1, end2,pre);
}

 

 

 

 

 3、已知前序后序遍历,求中序遍历:

这种情况并不能完全的求出所有情况的二叉树中序遍历。因为由前序和后序并不能完全确定一颗树。但是,如果已知是满二叉树或者完全二叉树的话,我想是可以的。

序:中左右   后序:左右中

思路是这样的:  

    前序的第一个节点和后序的最后一个节点一定是根节点,
    如果前序的第二个节点与后序的倒数第二个节点不相等,那么前序的第二节点是根的左子树,后序的倒数第二节点是根的右子树

    (但是 如果前序的第二个节点与后序的倒数第二个节点相等,那就不能确定到底是左子树还是右子树了,因为缺省一个子树中左与左中,中右与右中都会相等。所以这就需要题目有要求该树的特征了)

    然后再后序中找到左子树根节点,在后序中从左子树根节点结合前序左子树根节点开始递归上述得到根节点左子树的子树

    同样在前序中找到右子树根节点,在前序中从右子树根节点结合后序右子树根节点开始递归上述得到根节点右子树的子树

改天想写代码的时候再来试试贴上吧

 

posted @ 2017-03-25 09:40  糯米米一粒  阅读(9620)  评论(1编辑  收藏  举报