剑指offer——面试题7:重建二叉树
// 面试题7:重建二叉树
// 题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输
// 入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,
// 2, 4, 7, 3, 5, 6, 8}和中序遍历序列{4, 7, 2, 1, 5, 3, 8, 6},则重建出
// 图2.6所示的二叉树并输出它的头结点。 #include <iostream>
#include <exception>
#include <cstdio>
#include<stdexcept>
using namespace std; struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
}; BinaryTreeNode* CreateBinaryTreeNode(int value)
{
BinaryTreeNode* pNode = new BinaryTreeNode();
pNode->m_nValue = value;
pNode->m_pLeft = nullptr;
pNode->m_pRight = nullptr; return pNode;
} void ConnectTreeNodes(BinaryTreeNode* pParent, BinaryTreeNode* pLeft, BinaryTreeNode* pRight)
{
if(pParent != nullptr)
{
pParent->m_pLeft = pLeft;
pParent->m_pRight = pRight;
}
} void PrintTreeNode(const BinaryTreeNode* pNode)
{
if(pNode != nullptr)
{
printf("value of this node is: %d\n", pNode->m_nValue); if(pNode->m_pLeft != nullptr)
printf("value of its left child is: %d.\n", pNode->m_pLeft->m_nValue);
else
printf("left child is nullptr.\n"); if(pNode->m_pRight != nullptr)
printf("value of its right child is: %d.\n", pNode->m_pRight->m_nValue);
else
printf("right child is nullptr.\n");
}
else
{
printf("this node is nullptr.\n");
} printf("\n");
} void PrintTree(const BinaryTreeNode* pRoot)
{
PrintTreeNode(pRoot); if(pRoot != nullptr)
{
if(pRoot->m_pLeft != nullptr)
PrintTree(pRoot->m_pLeft); if(pRoot->m_pRight != nullptr)
PrintTree(pRoot->m_pRight);
}
} void DestroyTree(BinaryTreeNode* pRoot)
{
if(pRoot != nullptr)
{
BinaryTreeNode* pLeft = pRoot->m_pLeft;
BinaryTreeNode* pRight = pRoot->m_pRight; delete pRoot;
pRoot = nullptr; DestroyTree(pLeft);
DestroyTree(pRight);
}
} BinaryTreeNode* ConstructCore(int* startPreorder, int* endPreorder, int* startInorder, int* endInorder); BinaryTreeNode* Construct(int* preorder, int* inorder, int length)
{
if(preorder == nullptr || inorder == nullptr || length <= )
return nullptr; return ConstructCore(preorder, preorder + length - ,
inorder, inorder + length - );
} BinaryTreeNode* ConstructCore
(
int* startPreorder, int* endPreorder,
int* startInorder, int* endInorder
)
{
// 前序遍历序列的第一个数字是根结点的值
int rootValue = startPreorder[];
BinaryTreeNode* root = new BinaryTreeNode();
root->m_nValue = rootValue;
root->m_pLeft = root->m_pRight = nullptr; if(startPreorder == endPreorder)
{
if(startInorder == endInorder && *startPreorder == *startInorder)
return root;
else
{
std::logic_error ex("Invalid input.");
throw std::exception(ex);
}
// throw exception("Invalid input.");
} // 在中序遍历中找到根结点的值
int* rootInorder = startInorder;
while(rootInorder <= endInorder && *rootInorder != rootValue)
++ rootInorder; if(rootInorder == endInorder && *rootInorder != rootValue)
{
std::logic_error ex("Invalid input.");
throw std::exception(ex);
}
// throw std::exception("Invalid input."); int leftLength = rootInorder - startInorder;
int* leftPreorderEnd = startPreorder + leftLength;
if(leftLength > )
{
// 构建左子树
root->m_pLeft = ConstructCore(startPreorder + , leftPreorderEnd,
startInorder, rootInorder - );
}
if(leftLength < endPreorder - startPreorder)
{
// 构建右子树
root->m_pRight = ConstructCore(leftPreorderEnd + , endPreorder,
rootInorder + , endInorder);
} return root;
} // ====================测试代码====================
void Test(char* testName, int* preorder, int* inorder, int length)
{
if(testName != nullptr)
printf("%s begins:\n", testName); printf("The preorder sequence is: ");
for(int i = ; i < length; ++ i)
printf("%d ", preorder[i]);
printf("\n"); printf("The inorder sequence is: ");
for(int i = ; i < length; ++ i)
printf("%d ", inorder[i]);
printf("\n"); try
{
BinaryTreeNode* root = Construct(preorder, inorder, length);
PrintTree(root); DestroyTree(root);
}
catch(std::exception& exception)
{
printf("Invalid Input.\n");
}
} // 普通二叉树
// 1
// / \
// 2 3
// / / \
// 4 5 6
// \ /
// 7 8
void Test1()
{
const int length = ;
int preorder[length] = {, , , , , , , };
int inorder[length] = {, , , , , , , }; Test("Test1", preorder, inorder, length);
} // 所有结点都没有右子结点
// 1
// /
// 2
// /
// 3
// /
// 4
// /
//
void Test2()
{
const int length = ;
int preorder[length] = {, , , , };
int inorder[length] = {, , , , }; Test("Test2", preorder, inorder, length);
} // 所有结点都没有左子结点
// 1
// \
// 2
// \
// 3
// \
// 4
// \
// 5
void Test3()
{
const int length = ;
int preorder[length] = {, , , , };
int inorder[length] = {, , , , }; Test("Test3", preorder, inorder, length);
} // 树中只有一个结点
void Test4()
{
const int length = ;
int preorder[length] = {};
int inorder[length] = {}; Test("Test4", preorder, inorder, length);
} // 完全二叉树
// 1
// / \
// 2 3
// / \ / \
// 4 5 6 7
void Test5()
{
const int length = ;
int preorder[length] = {, , , , , , };
int inorder[length] = {, , , , , , }; Test("Test5", preorder, inorder, length);
} // 输入空指针
void Test6()
{
Test("Test6", nullptr, nullptr, );
} // 输入的两个序列不匹配
void Test7()
{
const int length = ;
int preorder[length] = {, , , , , , };
int inorder[length] = {, , , , , , }; Test("Test7: for unmatched input", preorder, inorder, length);
} int main(int argc, char* argv[])
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7(); return ;
}
剑指offer——面试题7:重建二叉树的更多相关文章
- 剑指offer面试题6 重建二叉树(c)
- 剑指offer面试题6 重建二叉树(java)
注:(1)java中树的构建 (2)构建子树时可以直接利用Arrays.copyOfRange(preorder, from, to),这个方法是左开右闭的 package com.xsf.SordF ...
- 剑指Offer:面试题6——重建二叉树(java实现)
问题描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不包含重复的数字. 例如: 输入:前序{1,2,4,7,3,5,6,8},中序{4,7,2,1 ...
- C++版 - 剑指Offer 面试题39:二叉树的深度(高度)(二叉树深度优先遍历dfs的应用) 题解
剑指Offer 面试题39:二叉树的深度(高度) 题目:输入一棵二叉树的根结点,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度.例如:输入二叉树 ...
- 剑指Offer - 九度1385 - 重建二叉树
剑指Offer - 九度1385 - 重建二叉树2013-11-23 23:53 题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的 ...
- 剑指offer_面试题6_重建二叉树(分解步骤,逐个击破)
题目:输入某二叉树的前序遍历和中序遍历的结果.请重建出该二叉树.如果输入的前序遍历和中序遍历的结果中都不含反复的数字. 比如:输入前序遍历 {1,2,4,7,3,5,6,8} 和中序遍历序列 {4,7 ...
- 剑指offer第二版-7.重建二叉树
描述:输入某二叉树的前序遍历和中序遍历结果,重建该二叉树.假设前序遍历或中序遍历的结果中无重复的数字. 思路:前序遍历的第一个元素为根节点的值,据此将中序遍历数组拆分为左子树+root+右子树,前序遍 ...
- 剑指offer【04】- 重建二叉树(java)
题目:重建二叉树 考点:树 题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6, ...
- 剑指offer(4)重建二叉树
题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ...
- 剑指offer——面试题8:二叉树的下一个节点
// 面试题8:二叉树的下一个结点 // 题目:给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点? // 树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指针. ...
随机推荐
- SQL Server 本地时间和UTC时间的相互转换
SET @UTCDate = DATEADD(hour, DATEDIFF(hour,GETDATE(),GETUTCDATE()), @LocalDate) SET @LocalDate2 = DA ...
- 第三周Linux编程实例练习
通过以下程序来练习 head.h # ifndef HEAD_H #define HEAD_H #include <stdio.h> int add(int,int); int sub(i ...
- HttpUploader6.2-process版本
1.优化JS逻辑,在上传前先同步相同文件进度,提高多用户上传效率. 2.优化文件块保存逻辑,减少相同文件块的写入操作,减少服务器IO操作,提高上传效率. js变化: up6.js新增UrlQuer ...
- ios PNG Crush error (PNG图片错误)
我是这么解决的: I had the same problem. How to fix : Open up image with Preview -> File > Export > ...
- 打造一套UI与后台并重.net通用权限管理系统
一.前言 从进行到软件开发这个行业现在已经有几年了,在整理出这个套开发框架之前自己做了不少重复造轮子的事.每次有新的项目总是要耗费不少时间在UI.权限和系统通用模块上面,自己累得要死,老板还骂没效率. ...
- Android自动提示控件:AutoCompleteTextView和MultiAutoCompleteTextView
在输入框中输入我们想要输入的信息就会出现其他与其相关的提示信息,这种效果在Android中是用AutoCompleteTextView实现的. 一.AutoCompleteTextView:单一匹配 ...
- arcgis for android常见问题回答
Q:arcgis for android最新版本是多少?(2014-7-18) Arcgis for android 10.2.3 sdk 百度盘下载地址:http://pan.baidu.com/s ...
- Arduino ADC + 模拟温度传感器LM35D
LM35是美国国家半导体(后被TI收购)推出的精密温度传感IC系列,其信号输出方式为模拟输出,输出电压值与摄氏温度值呈正比,且用户不需额外的校正就能获得较高的测量精度.其主要特性有: 供电电压:4~3 ...
- LSI SAS3IRCU配置SAS3系列RAID卡
LSI SAS3IRCU配置SAS3系列RAID卡 一.适用的controller LSISAS3008 LSISAS3004 二.名词解释 Controller: IR: Volume: 卷,基于物 ...
- webapi put 请求405问题
put 请求的时候 浏览器会像服务器发送两个请求 如何没做任何配置第一个options请求是会报错的 这是需要配置路由给options作响应 这时options请求就通过了,然后你们会看到你的put ...