剑指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:二叉树的下一个结点 // 题目:给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点? // 树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指针. ...
随机推荐
- 自定义JTabbedPane 标签风格
自定义JTabbedPane 标签风格 2012年03月09日 20:33:12 阅读数:2435 demo 下载地址:http://download.csdn.net/detail/jinannan ...
- [存储过程]中的事务(rollback)回滚
在编写SQL Server 事务相关的存储过程代码时,经常看到下面这样的写法: begin tran update statement 1 ... update statement 2 ... del ...
- web端测试点汇总
前言 前面一篇文章讲解了app测试一些功能点.那么相应的也梳理一下web测试相关的功能的测试点吧,此篇文章只是给你们一个思路,如果要涉及web端每个测试点,基本不可能实现的,所以只是提供一个设计的思路 ...
- Sublime for MacOS 使用技巧
1.创建软链接,使用命令直接打开sublime编辑器 ln -s "/Applications/Sublime Text.app/Contents/SharedSupport/bin/sub ...
- .net 空接合操作符 ??
C# 提供了一个所谓的 ”空接合操作符“ - 即??操作符,他要获取两个操作数. 假如左边的操作数部位null,就返回这个操作数.如果左边的操作数为null就返回右边. 空接合操作符一个妙处在于,它既 ...
- android和.net webservice中的DES加密算法
也是看了一堆的例子,本身并不会写加密算法,好在只要会用就行了,我们把在app中使用的参数加密,然后在.net端的webservice中进行解密,本身并没有什么问题,但是android下和.net下的d ...
- angular OnChange事件
import { Component, OnInit, Input, OnChanges, SimpleChanges } from '@angular/core'; @Component({ sel ...
- C# 抽象(4)
抽象类和普通类有区别嘛?在继承的时候,还是只能继承一次父类嘛? 答案: 抽象类除了在抽象方法和属性上面不能实现具体的代码之外和普通类没有区别.依旧符合类的基本特征.所以在继承的时候抽象类也是属于基类, ...
- Xcode打包提交至itunes connect后,提交审核成功,随后出现二进制文件无效
1.问题描述 Xcode打包提交至itunes connect后,提交审核成功,应用处于待审核状态,过了大概半个小时状态更改为二进制文件无效 2.原因分析 2.1 登陆在苹果中预留的邮箱 ---- 邮 ...
- CLion中出现错误add_dependencies called with incorrect number of arguments解决
出现这个错误以后我以为是IDE出现问题了,可是重新启动,打开其他的工程文件以后发现并没有这个错误,但是新建的文件却报错 然后就打开其他工程的Cmake_list.txt文件,发现最后一行是有工程文件夹 ...