java根据前序和中序建树_(Java实现)二叉树---根据前序、中序、后序数组还原二叉树...

article/2025/9/16 18:58:58

概述在上一篇文章中讲到顺序存储二叉树,一般是用于完全二叉树,通过统一的数学公式可以将数组还原成完全二叉树

而对于普通的二叉树来说,也可以根据前序、中序和后序遍历得到的数组,还原二叉树

还原还原的情况分两种,分别是根据前序、中序和根据中序、后序

采用的二叉树如下图所示:d2c54f9b3904e26c3527374dedb68300.png

注意:前序和后序是没有办法还原二叉树

根据前序、中序还原二叉树如下图所示:92afe7fb468b55d589b1427e2b727869.png

基本思路:根据前序数组,我们能够确定根节点(因为前序数组的根节点一定是第一个)

中序数组根据根节点能够确定左右子树的位置。(因为中序数组的根节点一定能够分开左右子树)

前序数组根据中序数组的左右子树的位置,也能够确定自己根节点的左右子树的位置(这部分可以看看代码怎么写的)

然后再分别递归左子树的前序、中序以及右子树的前序、中序,直到最后左右子树的长度都为0

代码如下:/**

* * @param pre 前序数组

* @param middle 中序数组

* @return 返回根节点

*/

public static TreeNode buildTree(int[] pre, int[] middle){

if (pre == null || middle == null || pre.length == 0 || middle.length == 0 || pre.length != middle.length)

return null;

//首先找到根节点

TreeNode root = new TreeNode(pre[0]);

//根据根节点的值找到中序遍历中的根节点的位置索引

int rootIndex = getIndex(middle, root.val);

if (rootIndex == -1)

return null;

//找到前序和中序中的左子树

//copyOfRange:拷贝[from, to)区间里的数据,左闭右开

int[] leftMiddle = Arrays.copyOfRange(middle, 0, rootIndex);

int[] leftPre = Arrays.copyOfRange(pre, 1, rootIndex + 1);

//找到前序和中序中的右子树

int[] rightMiddle = Arrays.copyOfRange(middle, rootIndex + 1, middle.length);

int[] rightPre = Arrays.copyOfRange(pre, rootIndex + 1, pre.length);

//用递归再次构建左右子树

TreeNode left = buildTree(leftPre, leftMiddle);

TreeNode right = buildTree(rightPre, rightMiddle);

//将左右子树添加到根节点上

root.left = left;

root.right = right;

return root;

}

根据中序、后序还原二叉树根据中序、后序和根据前序、中序是一样的道理,只不过是根节点从前序的第一个变为后序的最后一个,如下图所示:eb4c0c70ee21f1b777eddcdcae4f875e.png

代码如下://根据中序和后序还原二叉树

/**

* * @param middle 中序数组

* @param last 后序数组

* @return 根节点

*/

public static TreeNode buildTree2(int[] middle, int[] last){

if (middle == null || last == null) return null;

int middleLen = middle.length; //获取中序数组的长度

int lastLen = last.length; //获取后序数组的长度

if (middleLen == 0 || lastLen == 0) return null;

//首先根据后序获取根节点

TreeNode root = new TreeNode(last[lastLen - 1]);

//根据root获取中序的根节点的索引值

int rootIndex = getIndex(middle, root.val);

if (rootIndex == -1)

return null;

//找到中序和后序的左子树

int[] leftMiddle = Arrays.copyOfRange(middle, 0, rootIndex);

int[] leftLast = Arrays.copyOfRange(last, 0, rootIndex);

//找到中序和后序的右子树

int[] rightMiddle = Arrays.copyOfRange(middle, rootIndex + 1, middleLen);

int[] rightLast = Arrays.copyOfRange(last, rootIndex, lastLen - 1);

//用递归再次构建左子树和右子树

TreeNode left = buildTree2(leftMiddle, leftLast);

TreeNode right = buildTree2(rightMiddle, rightLast);

//将左右子树添加到根节点

root.left = left;

root.right = right;

return root;

}

总体代码//树节点:

public class TreeNode {

public int val;

public TreeNode left;

public TreeNode right;

public TreeNode(int val){

this.val = val;

}

}

//还原代码:

public class Travel {

public static void preorder_Traversal(TreeNode node){

if (node == null)

return;

System.out.println(node.val);

preorder_Traversal(node.left);

preorder_Traversal(node.right);

}

public static void inorder_Traversal(TreeNode node, int val){

if (node == null)

return;

inorder_Traversal(node.left, val);

System.out.println("---" + node.val);

if (node.val == val){

System.out.println("找到了:" + node.val);

return ; }

inorder_Traversal(node.right, val);

}

public static void postorder_Traversal(TreeNode node){

if (node == null)

return;

postorder_Traversal(node.left);

postorder_Traversal(node.right);

System.out.println(node.val);

}

public static int getIndex(int[] arr, int target){

for (int i = 0; i < arr.length; i ++){

if (arr[i] == target){

return i;

}

}

return -1;

}

//根据前序和中序还原二叉树

/**

* * @param pre 前序数组

* @param middle 中序数组

* @return 返回根节点

*/

public static TreeNode buildTree(int[] pre, int[] middle){

if (pre == null || middle == null || pre.length == 0 || middle.length == 0 || pre.length != middle.length)

return null;

//首先找到根节点

TreeNode root = new TreeNode(pre[0]);

//根据根节点的值找到中序遍历中的根节点的位置索引

int rootIndex = getIndex(middle, root.val);

if (rootIndex == -1)

return null;

//找到前序和中序中的左子树

//copyOfRange:拷贝[from, to)区间里的数据,左闭右开

int[] leftMiddle = Arrays.copyOfRange(middle, 0, rootIndex);

int[] leftPre = Arrays.copyOfRange(pre, 1, rootIndex + 1);

//找到前序和中序中的右子树

int[] rightMiddle = Arrays.copyOfRange(middle, rootIndex + 1, middle.length);

int[] rightPre = Arrays.copyOfRange(pre, rootIndex + 1, pre.length);

//用递归再次构建左右子树

TreeNode left = buildTree(leftPre, leftMiddle);

TreeNode right = buildTree(rightPre, rightMiddle);

//将左右子树添加到根节点上

root.left = left;

root.right = right;

return root;

}

//根据中序和后序还原二叉树

/**

* * @param middle 中序数组

* @param last 后序数组

* @return 根节点

*/

public static TreeNode buildTree2(int[] middle, int[] last){

if (middle == null || last == null) return null;

int middleLen = middle.length; //获取中序数组的长度

int lastLen = last.length; //获取后序数组的长度

if (middleLen == 0 || lastLen == 0) return null;

//首先根据后序获取根节点

TreeNode root = new TreeNode(last[lastLen - 1]);

//根据root获取中序的根节点的索引值

int rootIndex = getIndex(middle, root.val);

if (rootIndex == -1)

return null;

//找到中序和后序的左子树

int[] leftMiddle = Arrays.copyOfRange(middle, 0, rootIndex);

int[] leftLast = Arrays.copyOfRange(last, 0, rootIndex);

//找到中序和后序的右子树

int[] rightMiddle = Arrays.copyOfRange(middle, rootIndex + 1, middleLen);

int[] rightLast = Arrays.copyOfRange(last, rootIndex, lastLen - 1);

//用递归再次构建左子树和右子树

TreeNode left = buildTree2(leftMiddle, leftLast);

TreeNode right = buildTree2(rightMiddle, rightLast);

//将左右子树添加到根节点

root.left = left;

root.right = right;

return root;

}

public static void main(String[] args) {

//前序、中序测试

// int[] pre = {18, 20, 16, 29, 39, 8};

// int[] middle = {16, 20, 39, 8, 29, 18};

//

// TreeNode root = buildTree(pre, middle);

// preorder_Traversal(root);

//中序、后序测试

int[] middle = {16, 20, 18, 39, 29, 8};

int[] last = {16, 20, 39, 8, 29, 18};

TreeNode node = buildTree2(middle, last);

preorder_Traversal(node);

}

}


http://chatgpt.dhexx.cn/article/7XGK6Slk.shtml

相关文章

二叉树——前序和中序得到后序

由二叉树的前序和中序如何得到二叉树的后序呢&#xff1f;要给出答案&#xff0c;首先得明白什么是前序、中序、后序。 二叉树前序&#xff1a;遍历顺序为&#xff0c;根节点、左子树、右子树&#xff1b;中序&#xff1a;遍历顺序为&#xff0c;左子树、根节点、右子树&#…

二叉树的遍历|前序、中序、后序、层序遍历

文章目录 6.8 遍历二叉树6.8.1 二叉树遍历原理6.8.2 二叉树遍历方法1&#xff0e;前序遍历2&#xff0e;中序遍历3&#xff0e;后序遍历4&#xff0e;层序遍历 6.8.3 前序遍历算法6.8.4 中序遍历算法6.8.5 后序遍历算法6.8.6 推导遍历结果 6.8 遍历二叉树 6.8.1 二叉…

前序遍历二叉树

package cm.com.algorithm.tree;/*** 前序遍历2叉树* 前序遍历是指&#xff0c;对于树中的任意节点来说&#xff0c;先打印这个节点&#xff0c;然后再打印它的左子树&#xff0c;最后打印它的右子树** author liushuai13meicai.cn* date 2019-06-11 22:14*/ public class DLRT…

java根据前序和中序建树_Java实现根据前序遍历构建二叉树(前序遍历、中序遍历、后序遍历)...

Java实现根据前序遍历构建二叉树(前序遍历、中序遍历、后序遍历)&#xff0c;Java关于ACM的代码真的好少&#xff0c;想参考如何用java实现二叉树googl 前言 Java关于ACM的代码真的好少&#xff0c;想参考如何用java实现二叉树google了一上午都没找到资料&#xff0c;只能自己仿…

C实现前序遍历二叉树

1. 实验目的 &#xff08;1&#xff09;掌握二叉树的逻辑结构&#xff1b; &#xff08;2&#xff09;掌握二叉树的二叉链表存储结构&#xff1b; &#xff08;3&#xff09;验证二叉树的二叉链表存储及遍历操作。 2. 实验目的 &#xff08;1&#xff09;建立一棵含有n个结…

前序序列创建二叉树

7-9 前序序列创建二叉树 &#xff08;25 分&#xff09; 编一个程序&#xff0c;读入用户输入的一串先序遍历字符串&#xff0c;根据此字符串建立一个二叉树&#xff08;以二叉链表存储&#xff09;。 例如如下的先序遍历字符串&#xff1a; ABC##DE#G##F### 其中“#”表示的是…

按照前序遍历创建二叉树及树的四种遍历方式

一.二叉树的介绍 二叉树的特点是二叉树的每个结点的度都不大于2&#xff0c;可以视为每个结点都有左孩子和右孩子。故二叉树结点的数据结构为 二.二叉树的特点 1.设根结点所在的层数为第1层&#xff0c;则第i层最多有个结点。 2.深度为k的二叉树最多有个结点。 3.对任何一个二叉…

LeetCode 144. 二叉树的前序遍历(前序遍历)

文章目录 1. 题目信息2. 解题2.1 递归2.2 循环&#xff0c;必须掌握 1. 题目信息 给定一个二叉树&#xff0c;返回它的 前序 遍历。 示例:输入: [1,null,2,3] 1\2/3 输出: [1,2,3]进阶: 递归算法很简单&#xff0c;你可以通过迭代算法完成吗&#xff1f; 来源&#xff1a;力…

589. N 叉树的前序遍历(javascript)589. N-ary Tree Preorder Traversal

给定一个 n 叉树的根节点 root &#xff0c;返回 其节点值的 前序遍历 。 n 叉树 在输入中按层序遍历进行序列化表示&#xff0c;每组子节点由空值 null 分隔&#xff08;请参见示例&#xff09;。 Given the root of an n-ary tree, return the preorder traversal of its n…

python中while用法

python中while用法 例子&#xff1a; a1 while a<10:print(a)a2输出结果&#xff1a; 这段代码的意思是&#xff1a;a的初始值是1&#xff0c;判断条件是&#xff1a;如果a<10&#xff0c;则打印a&#xff0c;之后在返回的a的基础上加2&#xff0c;&#xff0c;如果a&…

while函数用法 matlab,Matlab(七)while循环的使用

Rate this post 在前一节课我们学习了if判断语句&#xff0c;在这篇博客&#xff0c;我们来学习循环语句&#xff1a;while 在此先打出一段简单的while循环代码&#xff1a; x1; while x<4 disp(x); x x1; end 在这段代码中&#xff0c;先声明x 1 当X < 4的时候&#x…

【JAVA】while的用法。

public class While { public static void main(String[] args) {//while 循环语句//不断重复完成某件工作&#xff0c;有明确的结束条件//for do whileint num0;//计数器while(num<10){ if(num%21){ num;continue;}//num为比6大的偶数时&#xff0c;循环结束if(num…

while在Java用法_while和do-while的使用方法

while循环开始后&#xff0c;先判别条件能否满足&#xff0c;假如满足就执行循环体内的语句&#xff0c;执行终了后再回来判别条件能否满足&#xff0c;如此无限反复&#xff1b;直到条件不满足时&#xff0c;执行while循环后边的语句。简单来讲就是说while循环是先判别后循环&…

y-在C语言while语句中的意义,c语言while用法(C语言while用法)

C语言while用法 需要稍作修改 #include main() { 5261int a,b,c,d; double e0.0; //这里e要初始化 a1,b1,c1; //b要从1开始&#xff0c;要不然第一个算4102不上 while(b<100) { ec*1.0/b;//要不然是整数1653除以整数&#xff0c;值是整数&#xff0c;也就是0 bb1; c-c; } pr…

php do while(),php do while用法详解

php do while是一种循环语句&#xff0c;该循环语句保证会执行一次&#xff0c;其使用语法如【<?php $i 0;do {echo $i;} while ($i > 0);?>】&#xff0c;其循环语句将正好运行一次。 推荐&#xff1a;《PHP视频教程》 do-while (PHP 4, PHP 5, PHP 7) do-while 循…

while在c语言中的作用,while的用法_C语言中while的用法

c语言中while的用法 当n==1时执行while循环结构里的语句,当n不等于1时,则跳过该循环执行循环体外的语句。 while 循环的格式:while (表达式){语句;} while 循环的执行顺序:当表达式为真,则执行下面的语句,语句执行完之后再判断表达式是否为真,如果为真,再次执行下面的…

PHP中用while的用法,php while语句的用法

在php中while语句指的是while循环语句&#xff0c;用于重复执行代码块&#xff0c;直到指定的条件不成立&#xff0c;其语法是【while (条件){要执行的代码;}】。 推荐&#xff1a;《PHP视频教程》 php while 循环 while 循环将重复执行代码块&#xff0c;直到指定的条件不成立…

三种循环语句的详解和使用(for,while,do-while)

对于刚接触编程的小可爱们&#xff0c;肯定会碰到这三种循环&#xff0c;书上写的有可能会过于专业化&#xff0c;会让我们感觉很难理解&#xff0c;在这里我就用最简洁明了的表达方式帮你理解并且学会使用这三种循环。 对于大佬们&#xff0c;读完你也许会新体会&#xff0c;新…

IO流(字符流)

IO流&#xff08;字符流&#xff09; 字符流 一.字符流是什么 字符流是可以直接读取字符的IO流字符流读取字符&#xff0c;就要先读去到字节数据&#xff0c;然后转为字符&#xff0c;如果要写出字符&#xff0c;需要把字符转为字节再写出 FileReader FileReader类的read(…