vlambda博客
学习文章列表

根据遍历序列创建二叉树

创建二叉树

一般情况下,二叉树的遍历序列有四种,分别是「先序遍历」、「中序遍历」、「后序遍历」以及「层序遍历」。(这里不考虑「Leetcode」上面其他乱七八糟的遍历方式).一种遍历方式是没有办法确定二叉树的,需要两种遍历方式,那么是不是这四种遍历方式随便找两种都可以呢,显然不是这样,正确的遍历方式应该是下面几种组合

  • 「先序遍历+中序遍历」
  • 「后序遍历+中序遍历」
  • 「层序遍历+中序遍历」

可以发现都带有「中序遍历」。事实上证明过程也比较容易,对数学比较敏感的读者,可以清楚的感觉应该用数学归纳法证明,这边不再一一赘述。下面举一个例子

  • 先序遍历序列为[3,9,20,15,7]
  • 中序遍历序列为[9,3,15,20,7]

由遍历顺序可以知道,先序遍历第一个访问的结点必然是根结点,这里是3,那么在中序遍历序列中可以找到3,3左边的必然是根结点的左子树,3右边的为根结点的右子树下面再依次递归建立左子树跟右子树。

最终的结果如图所示

前序+中序

struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){
    struct TreeNode *root=(struct TreeNode*)malloc(sizeof(struct TreeNode));
    if(preorderSize==0)return NULL;
    root->val=preorder[0];
    int leftLength=0,rightLength=0;
    for( leftLength=0;inorder[leftLength]!=preorder[0];leftLength++);
    rightLength=preorderSize-(1+leftLength);
    //create leftSubTree
    root->left=buildTree(preorder+1,leftLength,inorder,leftLength);
    //create rightSubTree
    root->right=buildTree(preorder+1+leftLength,rightLength,inorder+leftLength+1,rightLength);
    return root; 
}

后序+中序

struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize){
    if(postorderSize==0)
    return NULL;
    struct TreeNoderoot=(struct TreeNode*)malloc(sizeof(struct TreeNode));
    root->val=postorder[postorderSize-1];
    int leftLength=0,rightLength=0;
    for(leftLength=0;inorder[leftLength]!=postorder[postorderSize-1];leftLength++);
    rightLength=postorderSize-1-leftLength;
    root->left=createTree(inorder,leftLength,postorder,leftLength);
    root->right=createTree(inorder+leftLength+1,rightLength,postorder+leftLength,rightLength);
    return root;

}