重建二叉树
何海涛老师的《剑指offer》中的面试题6,觉着有难度,记录在此。
题目要求根据给出的前序遍历{1,2,4,7,3,5,6,8},中序遍历{4,7,2,1,5,3,8,6}重建它的二叉树,并且输出头指针。
首先必须知道前序遍历中序遍历的概念。在二叉树遍历中第一个总是根结点,但在中序遍历中根结点在中间。上述给的1就是根结点,中序遍历中1左边的就是左边结点,而右边的就是右边结点。这样接着在分出来的左边结点和右边结点中分别递归的方法完成。
递归的难点在于确定结束的条件,自己果然是经常写低级代码写习惯了,尝试多次未果,参考了何老师的代码:
1.首先取先序遍历的头结点生成一个二叉树结点。
2.利用该头节点将先序遍历,中序遍历中的左右结点序列分开得到left_preorder,right_preorder,left_inorder,right_inorder。
3.利用左中序序列的长度判断对应递归调用。
4.递归的结束条件是:中序遍历的首尾指针相同,且先序遍历序列首值与中序首值相同。
自己实现的代码如下:
BinaryTree* ConstructCore(int *start_preorder, int *end_preorder, int *start_inorder, int *end_inorder) { int root = start_preorder[0]; BinaryTree *pNode = new BinaryTree(root); if(start_preorder == end_preorder) { if(*start_preorder == *start_inorder && start_inorder == end_inorder) return pNode; else { throw std::exception("invalid input"); } } int *pMove = start_inorder; int left_elem_count = 0; while ( pMove != end_inorder && *pMove != root) { ++left_elem_count; ++pMove; } if(left_elem_count > 0) { pNode ->pLef = ConstructCore(start_preorder+1, start_preorder+left_elem_count, start_inorder, start_inorder+left_elem_count-1); } if(left_elem_count < end_preorder - start_preorder) { pNode ->pRig = ConstructCore(start_preorder+left_elem_count+1, end_preorder, start_inorder+left_elem_count+1, end_inorder); } return pNode; } BinaryTree* Construct(int *preorder, int *inorder, int length) { if(preorder == NULL || inorder==NULL || length<=0) return NULL; return ConstructCore(preorder, preorder+length-1, inorder, inorder+length-1); }
learn++