读书感悟:最近在看何海涛的《剑指Offer》一书,因为以前在学习数据结构的时候,二叉树编程学习的不是很好,经常拿到二叉树的问题,束手无策,这次经过思考,成功解决,算是小小的进步!
1、重建二叉树
题目:输入某二叉树的前序遍历和中序遍历结果,请重建该二叉树,假设输入的前序遍历和中序遍历的结果不含重复数字,例如输入的前序遍历序列{1,2,4,7,3,5,6,8} 和中序遍历序列{4,7,2,1,5,3,8,6}。
struct BinaryTreeNode
{
int value;
BinaryTreeNode* left;
BinaryTreeNode* right;
}
思路:在前序序列中,第一个值为1,则此为根节点,再在中序序列中找到1,以此为分界,前面的4,7,2便为左子树的节点,后面的5,3,8,6则为右子树的节点,采用递归的方法,左子树和右子树的建立又转化为与题目类似的问题。
现在我们要写的函数为,输入:前序遍历序列和中序遍历序列。返回:根节点指针。
我们经常不能理清递归过程,最主要的原因是没有很清楚的抓住递归的输入和返回值。如果我们在编程时,很清楚的理清递归函数的输入和返回,往往能很快的想清楚递归并解决问题。
在理清思路后,代码就不难写出了。递归代码如下:
BinaryTreeNode* Construct(int* preorder,int* inorder,int length) //preorder指向前序序列,inorder指向中序序列
//lenhth为节点个数
{
if(length<=0 || preorder==null || inorder==null)
retrun null; //判断是否为空
int* endPreorder;
int* endInorder;
return ConstructCore(preorder,endPreorder,inorder,endInorder);
}
BinaryTreeNode* ConstructCore(int* startPreorder,int* endPreorder,int* startInorder,int* endInorder)
{
int rootValue;
BinaryTreeNode* root=new BinaryTreeNode();
root->value=*startPreorder;
rootValue=*startPreorder;
root->left=null;
root->right=null;
if(startPreorder==endPreorder) //当两种序列的长度为1时
{
if(startInorder==endInorder && *startPreorder==*startInorder)
{
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* leftEndPreorder=startPreorder+leftLength;
if(leftLength>0)
{
root->left
=ConstructCore(startPreorder+1,leftEndPreorder,startInorder,rootInorder-1);
}
if(length<endPreorder-startPreorder)
{
root->right
=ConstructCore(letfEndPreorder+1,endPreorder,rootInorder+1,endInorder);
}
return root;
}
2、 编程时遇到的小知识
在编程时,遇到int型指针的指向问题。
int a[]={1,2,3,4};
*(a+1)=2;
因为这里的指针是与数据类型相关的,在指针+1,其地址自动+4,指向数组下一个坐标。