你好!二叉树【JAVA】

1.二叉树

节点组成,并且每个节点最多有两个子节点,分别称为左子节点右子节点,不存在子节点的节点称为叶子节点。二叉树常见的遍历方式有前序遍历中序遍历以及后序遍历前序遍历先遍历根节点然后遍历左子树和右子树中序遍历先遍历左子树,然后遍历根节点和右子树后序遍历先遍历左子树和右子树,最后遍历根节点

2.满|完全二叉树 

如果该二叉树的所有叶子节点都在最后一层,并且结点总数=2^n-1,n 为层数,则我们称为满二叉树 

如果该二叉树的所有叶子节点都在最后一层或者倒数第二层,而且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续,我们称为完全二叉树

 

3.二叉树遍历 

三种方式:

  • 1.前序遍历
  • 2.中序遍历
  • 3.后序遍历 

注:根据根节点的输出顺序,判断是前中后遍历~      

3.1.前序遍历

前序遍历:先访问根节点再访问左子树最后访问右子树

1.思路分析 

  • 1.先输出当前节点(根节点)
  • 2.若左子节点不为空,则递归继续遍历
  • 3.若右子节点不为空,则递归继续遍历

2.代码实战 

    /**
     * 前序遍历
     */
    public void preOrder() {
        System.out.println(this);//先输出根节点
        //向左子节点递归
        if (this.left != null) {
            this.left.preOrder();
        }
        //向右子节点递归
        if (this.right != null) {
            this.right.preOrder();
        }

3.2.中序遍历

中序遍历:先遍历左子树再输出根节点再遍历右子树

1.思路分析 

1.若当前节点的左子节点不为空,则递归遍历

2.输出当前节点(根节点)

3.若当前节点的左子节点不为空,则递归遍历

2.代码实战 

    /**
     * 中序遍历
     */
    public void infixOrder() {
        //先递归左子节点遍历
        if (this.left != null) {
            this.left.infixOrder();
        }
        //输出当前节点
        System.out.println(this);
        //递归右子节点遍历
        if (this.right != null) {
            this.right.infixOrder();
        }

3.3.后序遍历 

后序遍历:先遍历左子树再遍历右子树最后输出根节点

1.思路分析  

1.若当前节点的左子节点不为空,则递归遍历

2.若当前节点的右子节点不为空,则递归遍历

3.输出当前节点(根节点)

2.代码实战 

/**
     * 后序遍历
     */
    public void postOrder() {
        if (this.left != null) {
            this.left.postOrder();
        }
        if (this.right != null) {
            this.right.postOrder();
        }
        System.out.println(this);
    }

3.4创建二叉树遍历

/**
 * 定义一个二叉树
 */
class Tree {
    private HeroNode root;

    public void setRoot(HeroNode 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("当前二叉树为空无法遍历");
        }
    }
}

 

4.查找指定节点 

三种方式:

  • 1.前序查找
  • 2.中序查找
  • 3.后序查找 

注:后序查找相对比较快一点~

4.1.前序查找

1.思路分析

  • 1.判断当前节点是否是要查找的
  • 2.若相等,则返回
  • 3.若不相等,则判断当前节点的左子节点是否为空,不为空,向左递归查找
  • 4.若左递归找到,则返回。否则继续判断当前节点的右子节点是否为空,若不为空,则向右递归

2.代码实现

    /**
     * 前序查找
     */
    public HeroNode preOrderSearch(int no) {
        //判断当前节点是否相等
        if (this.no == no) {
            return this;
        }
        //定义变量,接收递归返回值
        HeroNode tempNode = null;
        //判断左子节点是否为空,向左子节点递归
        if (this.left != null) {
            tempNode = this.left.preOrderSearch(no);
        }
        //说明左递归找到
        if (tempNode != null) {
            return tempNode;
        }
        //左递归未找到,判断右子节点是否为空,并向右递归
        if (this.right != null) {
            tempNode = this.right.preOrderSearch(no);
        }
        return tempNode;
    }

4.2.中序查找

1.思路分析

1.判断当前节点的左子节点是否为空,若不为空,则向左递归

2.如果找到,则返回;

3.如果没有找到,则和当前节点比较,如果相等,则返回当前接节点,否则继续右递归

4.如果右递归找到,则返回,否则返回null

2.代码实现

    /**
     * 中序查找
     */
    public HeroNode infixOrderSearch(int no) {
        HeroNode tempNode = null;
        //判断当前节点的左子节点是否为空,并递归
        if (this.left != null) {
            tempNode = this.left.infixOrderSearch(no);
        }
        //判断是否找到
        if (tempNode != null) {
            return tempNode;
        }
        //未找到,判断当前节点是否相等
        if (this.no==no){
            return this;
        }
        //不等,判断右子节点是否为空,向有递归
        if (this.right!=null){
            tempNode=this.right.infixOrderSearch(no);
        }
        return tempNode;
    }

4.3.后序查找

1.思路分析

1.判断当前节点的左子节点是否为空,如果不为空,则左递归查找

2.如果找到,则返回,如果没有找到,判断当前接待的右子节点是否为空,如果不为空,则有递归查找,如果找到,则返回

3.如果有递归没有找到,就和当前节点比较,找到则返回,否则返回null

2.代码实现

    /**
     * 后序查找
     */
    public HeroNode postOrderSearch(int no){
        HeroNode tempNode=null;
        //判断当前节点的左子节点
        if (this.left!=null){
            tempNode=this.left.postOrderSearch(no);
        }
        //判断是否找到
        if (tempNode!=null){
            return tempNode;
        }
        //未找到,判断右子节点是否为空,并递归
        if (this.right!=null){
            tempNode=this.right.postOrderSearch(no);
        }
        //判断有递归是否找到
        if (tempNode!=null){
            return tempNode;
        }
        //左右均未找到,比较当前节点
        if (this.no==no){
            return this;
        }
        return tempNode;
    }

4.4创建二叉树查找

/**
 * 定义一个二叉树
 */
class Tree {
    private HeroNode root;

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

    //前序查找
    public HeroNode preOrderSearch(int no) {
        if (this.root != null) {
            return this.root.preOrderSearch(no);
        } else {
            return null;
        }
    }

    //中序查找
    public HeroNode infixOrderSearch(int no) {
        if (this.root != null) {
            return this.root.infixOrderSearch(no);
        } else {
            return null;
        }
    }

    //后序查找
    public HeroNode postOrderSearch(int no) {
        if (this.root != null) {
            return this.root.postOrderSearch(no);
        } else {
            return null;
        }
    }
}

 

5.删除节点 

  • 如果删除的节点是叶子节点,则删除该节点
  • 如果删除的节点是非叶子节点,则删除该子树

5.1思路分析

  • 1.当前二叉树是单向的,判断当前节点的子节点是否是要删除的节点,而不能判断,当前节点是不是要删除的
  • 2.如果当前节点的左子节点不为空,并且左子节点就是我们要删除的,就将this.left=null,并返回,结束;否则看右子节点
  • 3.如果当前节点的右子节点不为空,并且右子节点就是要删除的节点,就将this.rigth=null,并返回,结束;
  • 4.如果第二步,第三步递归都没有删除,则需要向左子树递归删除,如果左递归没有删除,则向右子树递归删除

5.2代码实现

    /**
     * 递归删除节点
     */
    public void deleteNode(int no) {
        //当前节点的左子节点不为空,并且是要删除的节点,则置为空
        if (this.left != null && this.left.no == no) {
            this.left = null;
            return;
        }
        //当前节点的右子节点不为空,并且是要删除的节点,则置为空
        if (this.right != null && this.right.no == no) {
            this.right = null;
            return;
        }
        //向左子树递归
        if (this.left != null) {
            this.left.deleteNode(no);
        }
        //向右子树递归
        if (this.right != null) {
            this.right.deleteNode(no);
        }
    }

5.3创建二叉树删除 

/**
 * 定义一个二叉树
 */
class Tree {
    private HeroNode root;

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

    //删除指定节点
    public void deleteNode(int no) {
        if (this.root != null) {
            //如果只有一个root节点,判断root是否是要删除的
            if (root.getNo() == no) {
                root = null;
                return;
            }else {
                root.deleteNode(no);
            }
        } else {
            System.out.println("空树无法删除");
        }
    }
}

 

6.顺序存储二叉树 

顺序存储二叉树,也称为顺序存储结构,是一种二叉树的存储方法。在顺序存储结构中,将二叉树的节点按照层次顺序存储在一个数组,使得二叉树的节点可以用数组元素来表示。通常采用广义表的形式将整棵树存储在一个一维数组中,而且该数组满足完全二叉树的特性。

1.数组方式存放arr=【1,2,3,4,5,6,7】

2.依然可以使用前序、中序、后序遍历  

6.1顺序存储二叉树的特点 

  • 顺序二叉树通常只考虑完全二叉树
  • 第n个元素的左子节点为2*n+1
  • 第n个元素的右子节点为2*n+2
  • 第n个元素的父节点为(n-1)/2

注:n表示二叉树中的第几个元素(下标从0开始)

6.2代码实现

/**
 * 创建二叉树,实现顺序存储
 */
class ArrTree {
    private int[] arr;

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

    //前序存储二叉树
    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);
        }
    }

    //中序存储二叉树
    public void infixOrder(int index) {
        if (arr == null || arr.length == 0) {
            System.out.println();
        }
        if ((index * 2 + 1) < arr.length) {
            infixOrder(index * 2 + 1);
        }
        System.out.println(arr[index]);
        //向右递归
        if ((index * 2 + 2) < arr.length) {
            preOrder(index * 2 + 2);
        }
    }

    //后序存储二叉树
    public void postOrder(int index) {
        if (arr == null || arr.length == 0) {
            System.out.println();
        }
        if ((index * 2 + 1) < arr.length) {
            infixOrder(index * 2 + 1);
        }
        //向右递归
        if ((index * 2 + 2) < arr.length) {
            preOrder(index * 2 + 2);
        }
        System.out.println(arr[index]);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会敲代码的小张

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值