重建二叉树
来源:互联网 发布:chrome 无法调用 java 编辑:程序博客网 时间:2024/06/04 19:16
以下题目内容来自《剑指Offer》
题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重新构造出该二叉树。假设输入的前序遍历和中序遍历的结果中不包含重复的数字。例如输入的前序遍历序列为{1,2,4,7,3,5,6,8}和中序遍历为{4,7,2,1,5,3,6,8},则重建出二叉树并输出它的头结点。
在二叉树的前序遍历序列中,第一个数字总是树的根节点的值。但在中序遍历中,根节点的值在序列的中间,左子树的结点的值位于根节点的值的左边,而右子树的结点的值位于根节点的右边。因此我们需要扫描中序遍历序列,才能找到根节点的值。
如图所示,前序遍历序列的第一个数字1就是根节点的值。扫描中序遍历序列,就能确定根节点的值的位置。根据中序遍历的特点,在根节点的值1前面3个数字都是左子树结点的值,位于1后面的数字都是右子树结点的值。
由于中序遍历序列中,有3个数字是左子树结点的值,因此左子树总共有3个左子结点。同样,在前序遍历的序列中,根节点后面的3个数字就是3个左子树结点的值,再后面的所有数字都是右子树结点的值。这样我们就在前序遍历和中序遍历两个序列中,分别找到了左右子树对应的子序列。
既然我们已经分别找到了左、右子树的前序遍历序列和中序遍历序列,我们可以用同样的方法分别去构建左右子树。也就是说,接下来的事情可以用递归的方法去完成。
书中只给出了思路和C++代码,根据这个思路,我用java实现,代码如下:
package com.sOffer;/** * 根据前序遍历和中序遍历重建二叉树 * @author lhqj * */class TreeNode{ int val; TreeNode leftNode; TreeNode rightNode; public TreeNode(int val){ this.val = val; }}public class Main2 { public static void main(String[] args) { int[] preOrder={1,2,4,7,3,5,6,8}; int[] inOrder={4,7,2,1,5,3,8,6}; System.out.println(Construct(preOrder,inOrder).val); } private static TreeNode Construct(int[] preOrder,int[]inOrder){ if(preOrder == null || inOrder == null) return null; return ConstructCore(preOrder,0,preOrder.length - 1,inOrder,0,inOrder.length - 1); } private static TreeNode ConstructCore(int[]preOrder,int sPreIndex,int ePreIndex,int[]inOrder,int sInIndex,int eInIndex){ //前序遍历序列的第一个数字就是根节点的值 int rootVal = preOrder[sPreIndex]; TreeNode root = new TreeNode(rootVal); root.leftNode = null; root.rightNode = null; if(sPreIndex == ePreIndex){//只有一个元素 if(sInIndex == eInIndex && preOrder[sPreIndex] == inOrder[sInIndex]){// return root; }else{ try { throw new Exception (); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //在中序遍历中找到根节点的值,再分为左子树和右子树 int rootIndex = sInIndex; while(rootIndex <= eInIndex && inOrder[rootIndex] != rootVal){ ++rootIndex; } //中序最后一个就是根节点,那么这棵树是没有右子树的,那输入的参数有问题 if(rootIndex == eInIndex && inOrder[rootIndex]!=rootVal){ try { throw new Exception (); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } int leftLen = rootIndex - sInIndex;//左子树的节点个数 int leftPreOrderEndIndex = sPreIndex + leftLen;//对应前序序列中的左子树节点位置 if(leftLen > 0){ //构建左子树 root.leftNode = ConstructCore(preOrder, sPreIndex + 1, leftPreOrderEndIndex, inOrder, sInIndex, rootIndex - 1); } if(leftLen < ePreIndex - sPreIndex){//右子树还有 //构建右子树 root.rightNode = ConstructCore(preOrder, leftPreOrderEndIndex + 1, ePreIndex, inOrder, rootIndex + 1, eInIndex); } return root; }}
通过递归调用,通过前序遍历序列得知当前子树的根节点,再根据中序遍历得知以当前根节点为根的子树的左右子树中 的节点,一步一步的从子节点到子数再到左(右)子树。
0 0
- 3.9重建二叉树
- 重建二叉树
- 二叉树重建
- 二叉树重建
- 二叉树的重建
- 重建二叉树
- 重建二叉树
- 重建二叉树
- 重建二叉树
- 重建二叉树
- 重建二叉树
- 重建二叉树
- 重建二叉树
- 二叉树重建
- 二叉树重建
- 重建二叉树
- 重建二叉树
- 重建二叉树
- 关于android6.0系统源码中出现DeskClock调用v7包中ActionBar其无法用物理按键控制其Tab上焦点的问题
- 什么是模块化
- 盘点2016年人工智能与深度学习领域的十大收购
- 理解 iOS 的内存管理(转)
- 广度优先、深度优先搜索算法——LeetCode
- 重建二叉树
- [Android Studio系列(三)]Android Studio 编译、同步慢的解决方法
- Axis2 service.xml发布webservice 两种配置方式
- Java 类的热替换 —— 概念、设计与实现
- Codeforces Aim Tech Round 3 (Div.2 )B.Checkpoints【思维】
- 欢迎使用CSDN-markdown编辑器
- app上架报错90362
- Andorid 小心 .getText().equals("")和.getText().toString().equals("")
- 冒泡排序