二叉树的遍历

关于二叉树的遍历,往往会出这么几类题目:

1. 根据一种序列重建二叉树

分析:只给出一个输出序列会对应多种二叉树,因此这类题目的给定序列中往往包含有空节点,这时只需要反过来写递归程序便可:
例:1086 Tree Traversals Again (25)(25 分)
程:

int times = 0;                //计数变量
node * build()
{
    node * r = NULL;         //根节点指针
    if( times < 2*N )            //若输入N个数据,则二叉树有2*N个节点    
    {
        int tem;            
        cin >> tem;
        if( tem !=  -1 )        //若输入不是-1
        {
            r = new node;    
            r -> num = tem;    //建立根节点
            times++;
        }
        else
        {                    //若是-1
            times++;
            return NULL;    //返回空指针
        }
            r->left = build();        //递归调用 ,建立leftchild
            r->right = build();    //递归调用,建立rightchild
    }
    return r;                //返回建立好的二叉树(pre-order)
}

2.根据先序中序遍历

分析: 既然给出了两种序列,那么序列中一定不包含空节点的输出,对于这种问题其解题的核心在于找到根节点位置
那么,如何找到根节点的位置呢?这就得利用中序遍历序列了。
例:1138 Postorder Traversal(25 分)
程:

void build(int root, int start, int end)
{
    if(start > end)
        return;
    int i = start;
    for(; inorder[i] != post[root]); i++);
    /************************
            do something
    ************************/
    build( root + 1,start,i-1);
    build( root + (i-start) + 1, i+1 , end);
}

析:
例如先序与中序分别是是:

1 2 3 4 5 6 7
2 3 1 5 4 7 6

根据先序序列,我们能够知道,根节点是1,那么2节点是1的左孩子(先序遍历的特性)。那么右节点在哪呢?
如果我们再看看中序序列,我们就可以清楚地发现树的结构是这样的:

           1
{2 3}          {5 4 7 6}

所以,先序序列的排布方式会是这样:

根 |   左   |      右 
 1  | 2   3  | 4   5   6   7

递归程序的接口设计为根节点的位置(先序),树的范围(中序)。
根据中序序列确定子树的范围和子树的根节点位置。

3.根据先序后序遍历

例:1119 Pre-and Post-order Traversals(30 分)
程:

void build(int preStart, int preEnd, int postStart, int postEnd)
{       
        if(preStart == preEnd)
        {
                v.push_back(preorder[preStart]);        
                return ;
        }
        if(preorder[preStart] == postorder[postEnd])
        {
                int i = preStart + 1;
                for(; i < preEnd && preorder[i] != postorder[postEnd-1]; i++); // find the root of right child in preorder sequence
                if(i - preStart > 1)
                        build(preStart + 1,i-1,postStart,postStart+(i - preStart-1) - 1);
                else
                        unique = false;
                v.push_back(preorder[preStart]);
                build(i,preEnd,postStart + (i - preStart-1),postEnd - 1);
        }
}

析:首先需要说明的是,根据先序与后序而确定的二叉树并不唯一。
解决这个问题的核心在于树的划分

感谢稀稀拉拉的赞赏