剑指offer--重建二叉树
来源:互联网 发布:seo教程 百度云 编辑:程序博客网 时间:2024/06/01 13:26
记录来自《剑指offer》上的算法题目。
题目如下:
输入某二叉树的前序遍历和中序遍历的结果,请重构出该二叉树。假设输入的前序遍历和中序遍历的结果都不含重复的数字。
二叉树的结点定义如下:
struct BinaryTreeNode{ int m_nValue; BinaryTreeNode* m_pLeft; BinaryTreeNode* m_pRight;};
实现代码如下:
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; 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 = startPreorder + leftLength; if (leftLength > 0){ // 构建左子树 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;}// 重建二叉树,根据输入的前序序列和中序序列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);}
测试代码如下:
// 前序遍历输出void PreOutput(BinaryTreeNode* root){ if (root == NULL) return; cout << root->m_nValue << " "; PreOutput(root->m_pLeft); PreOutput(root->m_pRight);}// 中序遍历输出void InOutput(BinaryTreeNode* root){ if (root == NULL) return; InOutput(root->m_pLeft); cout << root->m_nValue << " "; InOutput(root->m_pRight);}// 测试int main(void){ // 不完全二叉树 int pre1[] = {1,2,4,7,3,5,6,8}; int in1[] = {4,7,2,1,5,3,8,6}; BinaryTreeNode* root = Construct(pre1, in1, 8); cout << "不完全二叉树前序遍历输出:"; PreOutput(root); cout << endl; cout << "中序遍历输出:"; InOutput(root); cout << endl; // 完全二叉树 int pre2[] = { 1, 2, 4, 8, 9, 5, 3, 6, 7 }; int in2[] = { 8, 4, 9, 2, 5, 1, 6, 3, 7 }; root = Construct(pre2, in2, 9); cout << "\n完全二叉树前序遍历输出:"; PreOutput(root); cout << endl; cout << "中序遍历输出:"; InOutput(root); cout << endl; // 所有结点都没有右子结点的二叉树,即左斜树 int pre3[] = { 1, 2, 3, 4, 5 }; int in3[] = { 5, 4, 3, 2, 1 }; root = Construct(pre3, in3, 5); cout << "\n左斜树前序遍历输出:"; PreOutput(root); cout << endl; cout << "中序遍历输出:"; InOutput(root); cout << endl; // 右斜树 int pre4[] = { 1, 2, 3, 4, 5 }; int in4[] = { 1, 2, 3, 4, 5 }; root = Construct(pre4, in4, 5); cout << "\n右斜树前序遍历输出:"; PreOutput(root); cout << endl; cout << "中序遍历输出:"; InOutput(root); cout << endl; // 只有一个结点的二叉树 int pre5[] = { 5 }; int in5[] = { 5 }; root = Construct(pre5, in5, 1); cout << "\n一个结点的二叉树前序遍历输出:"; PreOutput(root); cout << endl; cout << "中序遍历输出:"; InOutput(root); cout << endl; // 二叉树的根结点指针是NULL int pre7[] = { 5 }; int in7[] = { 5 }; root = Construct(pre5, in5, 0); system("pause"); return 0;}
在函数ConstructCore
中,先根据前序序列的第一个数字创建根结点,然后在中序序列中找到根结点的位置,这样就能确定左右子树的数量,在前序遍历和中序遍历的序列中划分了左、右子树结点的值后,就可以递归地调用函数ConstructCore
,去分别构建它的左右子树。
完整的例子可以查看我的Github。
0 0
- [剑指offer]重建二叉树
- 【剑指offer】重建二叉树
- 剑指offer--重建二叉树
- 剑指offer---重建二叉树
- 剑指Offer-重建二叉树
- 剑指offer:重建二叉树
- 剑指offer-重建二叉树
- 《剑指offer》重建二叉树
- 【剑指Offer】重建二叉树
- 剑指offer-重建二叉树
- 《剑指offer》-重建二叉树
- 剑指offer 重建二叉树
- 剑指offer:重建二叉树
- 【剑指offer】重建二叉树
- 剑指offer 重建二叉树
- [剑指offer]重建二叉树
- 剑指offer--重建二叉树
- 《剑指offer》重建二叉树
- Python 杂记-2
- 不一样的开源项目,诚邀认真的审稿小伙伴
- #Codeforces Round #384 (Div. 2) 题解(743A,743B,743C,743D,743E)
- SSL 1607 没有上司的晚会
- 十四周项目4
- 剑指offer--重建二叉树
- 【HNOI2008】GT考试
- 微软亚研
- imindmap 9
- OpenCV3.0中的离散傅里叶变换
- RCNN到YOLO
- hdu1015Safecracker
- 十四周项目5
- 字母缩写