重建二叉树
关于二叉树的重建,我总结如下,并以图文的形式展示:
一颗二叉树,已知先序遍历和中序遍历,要求还原出二叉树,问题不难,关键是细节:
思想:
1、先序遍历序列的第一个元素一定定是根节点,可以由此获取二叉树的根节点。
2、在中序遍历序列中查找到根节点,由中序遍历的性质可知,中序遍历中该根节点左边的序列一定在根节点的左子树中,而根节点右边的序列一定在右子树中。由此可以知道先序遍历中左子树以及右子树的起止位置。
3、分别对左子树和右子树重复上述的过程,直至所有的子树的起止位置相等时,说明已经到达叶子节点。
以上过程,递归就显得很重要:
先上一张图:
假设这是需要我们重新构建的二叉树。
此二叉树的前序遍历为:1,2,4,7,3,5,6,8
中序遍历为:4,7,2,1,5,3,8,6
再看:
同样的方法在子树中递归重建子树,以下是代码:
//声明重构 BinaryTreeNode* ConstructCore(int* startPreorder, int* endPreorder, int* startInorder, int* endInorder); //重构 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); } BinaryTreeNode* ConstructCore ( int* startPreorder, int* endPreorder, int* startInorder, int* endInorder ) { //前序遍历序列的第一个数字是根结点的值 int rootValue = startPreorder[0]; //重构第一个根节点 BinaryTreeNode* root = new BinaryTreeNode(); root->m_nValue = rootValue; root->m_pLeft = root->m_pRight = NULL; //前序的头和尾相等的时候 if(startPreorder == endPreorder) { //并且中序头和尾也相等,前序头和中序头相等,只说明只有一个节点 if (startInorder == endInorder && *startPreorder == *startInorder) { return root; } } // 在中序遍历中找到根结点的值 int* rootInorder = startInorder; while (rootInorder <= endInorder && *rootInorder != rootValue) { ++ rootInorder; } if (rootInorder == endInorder && *rootInorder != rootValue) { cout << "非法序列" << endl; return; } //while循环结束,跳过,意思是找到了根节点 //求出左子树的长度leftLength int leftLength = rootInorder - startInorder; //虽然是指针相减,但指针内部也是整数 int* leftPreorderEnd = startPreorder + leftLength; //找到前序遍历左子树最后一个节点 if(leftLength > 0) { // 构建左子树 //startPreorder + 1 原来前序的头往前走一个 root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd, startInorder, rootInorder - 1); } if(leftLength < endPreorder - startPreorder) { // 构建右子树 root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder, rootInorder + 1, endInorder); } return root; }赐教!