struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
// 输入:先序和中序的第一个指针和最后一个指针,
// 递归调用,每次缺点当前结点
BinaryTreeNode* ConstructCore(int* startPerorder, int* endPreorder, int* startInorder, int* endInorder)
{
//先序第一个为根节点
int rootValue = startPerorder[0];
BinaryTreeNode* root = new BinaryTreeNode;
root->m_nValue = rootValue;
root->m_pLeft = root->m_pRight = NULL;
//递归退出条件
if ( startPerorder==endPreorder )
{
if ( startInorder==endInorder && *startPerorder==*endInorder )
return root;
else
throw std::exception("Invalid input."); //异常处理
}
// 在中序遍历中找到根节点的值
int* rootInorder = startInorder;
while(rootInorder<=endInorder && *rootInorder!=rootValue)
++rootInorder;
//异常处理
if ( rootInorder==endInorder && *rootInorder!=rootValue)
throw std::exception("Invalid input.");
int leftLength = rootInorder - startInorder;
int* leftPreorderEnd = startPerorder+leftLength;
if ( leftLength > 0 )
{
//构建左子树
root->m_pLeft = ConstructCore(startPerorder+1,leftPreorderEnd,startInorder, rootInorder-1);
}
if ( leftLength < endPreorder-startPerorder )
{
//构建右子树
root->m_pRight = ConstructCore(leftPreorderEnd+1,endPreorder,rootInorder+1,endInorder);
}
return root;
}
//根据先序和中序构建二叉树
BinaryTreeNode* 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);
}
注:本题用递归解,首先得分析好每次递归做的相同事情是什么,其次,判断终止条件;最后,注意边界条件和异常处理。
递归虽然简洁,但它同时也有显著的缺点。
1、递归由于是函数调用自身,而函数调用是有时间和空间消耗的:每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址及临时变量,而且往栈里面压入数据和弹出数据都需要时间。这就不难理解递归效率不如非递归。
2、递归可能会引起严重的问题:调用栈溢出。前面分析中提到徐哎哟为每一次函数调用在内存栈中分配空间,而每个进程的栈的容量是有限的。递归调用的层级太多时,就会超出栈的容量,从而导致调用栈溢出。
参考:剑指offer