1.单前序遍历
import java.util.Scanner;
class TreeNode{
TreeNode left;
TreeNode right;
char val;
TreeNode( char val){
this.val=val; }
}
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String a = in.nextLine();
TreeNode root=creatTreeNode(a);
inorder(root);
}
//定义方法:根据前序遍历的字符串来创建二叉树
public static int i=0;
public static TreeNode creatTreeNode(String string){
if(i>=string.length()){
return null;
}
if(string.charAt(i)!='#'){
TreeNode root=new TreeNode(string.charAt(i));
i++;
root.left=creatTreeNode(string);
root.right=creatTreeNode(string);
return root;
}else{
i++;
return null;
}
}
//定义方法:中序遍历二叉树
public static void inorder(TreeNode root){
if(root==null){
return ;
}
inorder(root.left);
System.out.print(root.val+" ");
inorder(root.right);
}
}
1).题目分析
这道题是单前序遍历序列求二叉树并返回中序打印的结果.如果是正常的单前序遍历的结果字符串的话,其实不足以确定一颗二叉树.但是本题中的字符串在遍历到空的子树时返回了一个'#',这样就足以确定一个二叉树的结构.
2).自己创建TreeNode类
本题中并没有给出定义好的TreeNode类,例如像这种:
而Java标准库中没有现成的二叉树节点类.Java集合框架主要提供了像List、Set、Map这样的数据结构,但树结构通常用于特定算法问题,如二叉树遍历、搜索树操作等,而这些情况下需要根据具体需求定义节点结构.例如,TreeNode通常包含值、左子节点和右子节点的引用,这些属性需要根据问题定制.
3)int型变量i的定义
public static int i=0;
在递归构建二叉树时,i变量需要在多次递归中保持递增,确保递归正常进行.所以必须在方法外定义,不然每次递归调用都会重新初始化i,导致无法正确跟踪当前处理到的字符位置.
4)递归结束的条件
if(i>=string.length()){
return null;
}
当变量i大于等于string.length()时,数组下标越界,递归结束,返回null.
2.从前序与中序遍历序列构造二叉树
class Solution {
public int preIndex=0;
public TreeNode buildTree(int[] preorder, int[] inorder) {
return buildTreeChild(preorder,inorder,0,inorder.length-1);
}
public TreeNode buildTreeChild(int[]preorder,int[]inorder,int inbegin,int inend){
if(inend<inbegin){
return null;
}
//创建新树,因为是前序遍历,所以根是前序序列中的元素
TreeNode root=new TreeNode(preorder[preIndex]);
//找到中序遍历序列中对应的元素的下标
int rootIndex=findIndex(inorder,inbegin,inend,preorder[preIndex]);
preIndex++;
//左右子树
root.left=buildTreeChild(preorder,inorder,inbegin,rootIndex-1);
root.right=buildTreeChild(preorder,inorder,rootIndex+1,inend);
return root;}
//创建方法:在数组中查找1个值的下标
private int findIndex(int[] inorder,int inbegin,int inend,int key){
for(int i=inbegin;i<=inend;i++){
if(inorder[i]==key){
return i;
}
}
return -1;
}
}
1)题目分析
题目中给出前序遍历和中序遍历的结果,可以遍历前序遍历数组,因为中序遍历的遍历顺序是左孩子=>根节点=>右孩子,所以可以在中序遍历数组中找到对应的元素,它的左孩子在左边的数组中,右孩子在右边的数组中.
2)preIndex变量的定义
同一道题的i一样,preIndex需要定义在递归方法之外,来确保在多次递归当中,i的大小是递增的.
public int preIndex=0;
3)递归结束的条件
if(inend<inbegin){
return null;
}
这时右指针越过左指针,变成了-1,数组下标越界异常,递归返回.
3.从中序与后序遍历序列构造二叉树
class Solution {
public int postorderIndex;
public TreeNode buildTree(int[] inorder, int[] postorder) {
postorderIndex=postorder.length-1;
//中 后
return myBuildTree(inorder,postorder,0,inorder.length-1);
}
//定义方法:递归创建二叉树
public TreeNode myBuildTree(int[]inorder,int[]postorder,int inbegin,int inend){
if(inbegin>inend){
return null;
}
TreeNode root=new TreeNode(postorder[postorderIndex]);
int rootIndex=findIndex(inorder,inbegin,inend,postorder[postorderIndex]);
postorderIndex--;
root.right=myBuildTree(inorder,postorder,rootIndex+1,inend);
root.left=myBuildTree(inorder,postorder,inbegin,rootIndex-1);
return root;
}
//定义方法:查找数组中元素的下标
public int findIndex(int[]inorder,int inbegin,int inend,int val){
for(int i=0;i<=inend;i++){
if(inorder[i]==val){
return i;
}
}
return -1;
}
}
1)遍历顺序
因为这道题是用后序遍历中的元素去找中序遍历序列中的值,而后序遍历是按照左孩子=>右孩子=>根节点的顺序来遍历的,所以要从后往前遍历后序序列.
2)postorderIndex的初始值
因为postorderIndex是定义在方法之外的,所以postorderIndex不能一开始就为postorder数组的长度减一,要在方法中再进行赋值.