二叉树遍历思路

示例

1、前序遍历:
   a.先输出当前结点(初始时的时候是root节点)
   b.如果左子结点不为空,则递归继续前序遍历
   c.如果右子结点不为空,则递归继续前序遍历
如图遍历顺序为:12345

2、中序遍历:
   a.如果左子结点不为空,则递归继续中序遍历
   b.输出当前结点
   c.如果右子结点不为空,则递归继续中序遍历
如图遍历顺序为:21435

3、后序遍历:
   a.如果左子结点不为空,则递归继续后序遍历
   b.如果右子结点不为空,则递归继续后序遍历
   c.输出当前结点
如图遍历顺序为:24531

创建二叉树的数据结构

class HeroNode01{

    public int no;
    public String name;
    public HeroNode01 left; //左节点默认为Null
    public HeroNode01 right; //右节点 默认为null

    public HeroNode01(int no, String name) {
        this.no = no;
        this.name = name;
    }

    public HeroNode01() {
    }

    @Override
    public String toString() {
        return "HeroNode01{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public HeroNode01 getLeft() {
        return left;
    }

    public void setLeft(HeroNode01 left) {
        this.left = left;
    }

    public HeroNode01 getRight() {
        return right;
    }

    public void setRight(HeroNode01 right) {
        this.right = right;
    }



    //先序遍历
    public void preOrder(){

            //输出父节点
            System.out.println(this);

            //递归访问左子树
            if(this.left!=null){

                this.left.preOrder();
            }

            //递归访问右子树
            if (this.right!=null){

                this.right.preOrder();
            }

    }


    //中序遍历
    public void infixOrder(){

        //递归访问左子树
        if(this.left!=null){

            this.left.infixOrder();
        }

        //输出父节点
        System.out.println(this);

        //递归访问右子树
        if (this.right!=null){

            this.right.infixOrder();
        }



    }

    //后序遍历
    public void postOrder(){

        //递归访问左子树
        if(this.left!=null){

            this.left.postOrder();
        }

        //递归访问右子树
        if (this.right!=null){

            this.right.postOrder();
        }

        //输出父结点
        System.out.println(this);

    }

}

创建根结点数据结构

class BinaryTreeRoot{
    private HeroNode01 root;

    public void setRoot(HeroNode01 root) {
        this.root = root;
    }

    //先序遍历
    public void preOrder(){
        if(this.root!=null){
            this.root.preOrder();
        }else {
            System.out.println("二叉树为空,无法访问!");
        }
    }

    //中序遍历
    public void infixOrder(){
        if(this.root!=null){
            this.root.infixOrder();
        }else {
            System.out.println("二叉树为空,无法访问!");
        }
    }

    //后序遍历
    public void postOrder(){
        if(this.root!=null){
            this.root.postOrder();
        }else {
            System.out.println("二叉树为空,无法访问!");
        }
    }
}

手动创建一棵二叉树

  //首先创建一颗二叉树

        BinaryTreeRoot binaryTreeRoot=new BinaryTreeRoot();

        //创建需要的节点
        HeroNode01 root=new HeroNode01(1,"宋江");
        HeroNode01 node2=new HeroNode01(2,"吴用");
        HeroNode01 node3=new HeroNode01(3,"卢俊义");
        HeroNode01 node4=new HeroNode01(4,"林冲");
        HeroNode01 node5=new HeroNode01(5,"关胜");

        root.setLeft(node2);
        root.setRight(node3);
        node3.setLeft(node4);
        node3.setRight(node5);
        binaryTreeRoot.setRoot(root);

        //测试
        System.out.println("前序遍历");
        binaryTreeRoot.preOrder();

        //测试
        System.out.println("中序遍历");
        binaryTreeRoot.infixOrder();

        //测试
        System.out.println("后序遍历");
        binaryTreeRoot.postOrder();

二叉树-查找指定结点

思路分析:
    前序查找思路:
    1、先判断当前节点的no是否等于要查找的
    2、如果是相等,则返回当前节点
    3、如果不等,则判断当前节点的左子树是否为空,如果不为空,则
       递归前序查找。
    4、如果左递归前序查找找到该节点,则返回,否则继续判断,当前
       结点的右子结点是否为空,如果不空,则继续右递归前序查找。
     
    中序查找思路:
    1、判断当前节点的左子树节点是否为空,如果不为空,则递归中序 
       查找。
    2、如果找到,则返回,如果没有找到,就和当前结点比较,如果是 
       则返回当前结点,否则继续右递归中序查找
    3、如果右递归中序查找,找到就返回,否则返回Null
    
    后序查找思路:
    1、判断当前节点的左子树是否为空,如果不为空,则递归后序查找
    2、如果找到,就返回,如果没有找到,就判断当前结点的右子节点 
       是否为空,则右递归进行后序查找,如果找到,就返回。
    3、就和当前节点进行,比如,如果是则返回,否则返回null
    

前序查找

//前序查找
    public HeroNode01 preOrderSearch(int no) {
        System.out.println("进入前序查找:");
        //比较是不是当前结点
        if(this.no==no){
            return this;
        }
        //1.则判断当前结点的左子节点是否为空,如果不为空,则递归前序查找
        //2、如果左递归前序查找,找到结点,则返回
        HeroNode01 heroNode01=null;
        //递归访问左子树
        if(this.left!=null){

            heroNode01 = this.left.preOrderSearch(no);
        }

        if(heroNode01!=null){
            return heroNode01;
        }

        //1、左递归前序查找,找到该结点,则返回
        //2、当前结点的右子结点是否为空,如果不空则继续向右递归前序查找
        if (this.right!=null){

            heroNode01 = this.right.preOrderSearch(no);
        }
        return heroNode01;
    }

中序查找


    //中序查找
    public HeroNode01 infixOrderSearch(int no) {

        System.out.println("进入中序查找:");

        HeroNode01 heroNode01=null;

        //1、判断当前节点的左子树节点是否为空,如果不为空,则递归中序
        if(this.left!=null){
            heroNode01=this.left.infixOrderSearch(no);
        }

        //如果找到则直接返回,不用再继续向右查找
        if(heroNode01!=null){
            return heroNode01;
        }

        //如果找到则返回该结点
        if(this.no==no){
            return this;
        }

        //1、没有找到且右子树不为空则继续向右查找,
        //2、如果右递归中序查找,找到就返回,否则返回Null
        if(this.right!=null){
            heroNode01 = this.right.infixOrderSearch(no);
        }

        return heroNode01;

    }


   

后序查找

 //后序查找
    public HeroNode01 postOrderSearch(int no) {

        System.out.println("进入后序查找:");

        HeroNode01 heroNode01=null;

        //1、先判断当前结点的左子树是否为空,如果不为空,则递归后序查找
        if(this.left!=null){
            heroNode01 = this.left.postOrderSearch(no);
        }

        //2、如果左子树找到则返回
        if(heroNode01!=null){
            return heroNode01;
        }

        //3、否则则判断右子树是否为空不为空则继续向右递归查找
        if(this.right!=null){
            heroNode01=this.right.postOrderSearch(no);
        }

        //如果右子树找到则返回
        if(heroNode01!=null){
            return heroNode01;
        }

        //如果左右节点,都没有找到再来判断该结点
        if(this.no==no){
            return this;
        }

        return heroNode01;
    }

删除结点

规定:
    1)如果删除的结点是叶子结点,则删除该结点
    2)如果删除的是非叶子结点,则删除该子树
思路:
    首先:
        考虑如果树是空树root,如果只有一个root结点,则等价将二叉树置空
    然后:
        1、由于我们的二叉树是单向的,所以我们是判断当前节点的子节点是否是 
           需要删除的结点。
        2、如果当前结点的左子结点不为空,并且左子结点就是要删除结点,就将 
           this.left=null;并且就返回(结束递归删除)
        3、如果当前结点的右子结点不为空,并且右子结点就是要删除结点,就将 
           this.right=null;并且就返回(结束递归删除)
        4、如果第2步和第3步没有删除结点,那么我们就需要向左子树进行递归 
           删除。
        5、如果第4步也没有删除结点,则应该向右子树进行递归删除。
        
 public void delNode(int no){
        //2、如果当前结点的左子结点不为空,并且左子结点
        // 就是要删除结点,就将this.left=null;并且就返回(结束递归删除)
        if(this.left!=null && this.left.no==no){
            this.left=null;
            return;
        }

        //3、如果当前结点的右子结点不为空,并且右子结点就是要删除结点,就将
        // his.right=null;并且就返回(结束递归删除)
        if(this.right!=null && this.right.no==no){
            this.right=null;
            return;
        }

        //向左递归删除
        if(this.left!=null){
            this.left.delNode(no);
        }

        //向右递归删除
        if(this.right!=null){
            this.right.delNode(no);
        }


    }

顺序存储二叉树

从数据存储来看,数据存储方式和树的存储方式可以相互转换,即数组可以转换为树,树也可以转换为数组,如图所示:
示例

顺序二叉树的特点:
   1、顺序二叉树通常只考虑完全二叉树
   2、第n个元素的左子结点为 2*n+1
   3、第n个元素的右子结点为2*n+2
   4、第n个元素的父结点为(n-1)/2
   5、n表示二叉树中的第几个元素(按0开始编号如图所示:)

下面实现如图所示数组到树之间的转换,给出中序遍历和前序遍历两种方式。实现思想主要根据顺序二叉树的特点进行实现。

class ArrBinaryTree01{
    private int[] arr; //存储数据结点的数组

    public ArrBinaryTree01() {
    }

    public ArrBinaryTree01(int[] arr) {
        this.arr = arr;
    }

    //重装preOrder
    public void preOrder(){
        this.preOrder(0);
    }

    //编写一个方法,完成顺序存储二叉树的前序遍历
    /**
     * 前序遍历
     * @param index 数组下标
     */
    public void preOrder(int index){
        //如果数组为空,或者arr.length=0
        if(arr==null || arr.length==0){
            System.out.println("数组为空,不能按照二叉树的前序遍历");
        }

        //输出当前这个元素
        System.out.println(arr[index]);

        //向左递归遍历
        if(index*2+1<arr.length){
            preOrder(index*2+1);
        }

        //向右递归遍历
        if(index*2+2<arr.length){
            preOrder(index*2+2);
        }

    }

    //重装infixOrder
    public void infixOrder(){
        this.infixOrder(0);
    }

    /**
     * 中序遍历
     * @param index 数组下标
     */
    public void infixOrder(int index){
        //如果数组为空,或者arr.length=0
        if(arr==null || arr.length==0){
            System.out.println("数组为空,不能按照二叉树的前序遍历");
        }


        //向左递归遍历
        if(index*2+1<arr.length){
            preOrder(index*2+1);
        }

        //输出当前这个元素
        System.out.println(arr[index]);

        //向右递归遍历
        if(index*2+2<arr.length){
            preOrder(index*2+2);
        }
    }
}

大老板
4 声望0 粉丝

下一篇 »
JAVA技术面试