二叉树遍历

 

 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数组的长度减一,要在方法中再进行赋值.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值