二叉树-前序中序后续遍历,以及查找删除操作!

本文围绕二叉树展开,介绍了二叉树的基本概念,包括左右节点、叶子节点、满二叉树和完全二叉树等。详细阐述了二叉树的前序、中序、后序遍历思路及步骤,还说明了三种遍历方式下的查找思路,最后讲解了二叉树的删除操作思路并给出全代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、二叉树的介绍

1.二叉树:每个节点最多只能有两个子节点的一种形式的树
在这里插入图片描述
2.左右节点:也叫孩子节点,二叉树的子节点分为左节点和右节点,如图21为11的左子节点,31为11的右子节点,11为21和31的父节点
在这里插入图片描述
3.叶子节点:叶子节点就是树中最底段的节点,叶子节点没有子节点。
4.满二叉树:二叉树的所有叶子节点都在最后一层,并且满足节点总数为2^(n-1),n为层数。
在这里插入图片描述
5.完全二叉树:二叉树的所有叶子节点都在最后一层或者分布在倒数第二层,并且满足最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续!
在这里插入图片描述
6.满二叉树是完全二叉树的一个特列,但完全二叉树不一定是满二叉树

二、二叉树的前序,中序,后续遍历

1.逻辑结构示意图
在这里插入图片描述
2.前序中序后序遍历思路分析即步骤
1.创建一颗二叉树

2.前序遍历思路分析:
先输出父节点,在输出左子节点,在输出右子节点
步骤
①先输出当前节点(初始的时候是root节点)
②如果左子节点不为空,则左子节点递归继续前序遍历
③如果右子节点不为空,则右子节点递归继续前序遍历

3.中序遍历思路分析:
先输出左子节点,在输出父节点,在输出右子节点
步骤
3.1如果当前节点的左子节点不为空,则左子节点递归中序遍历,
3.2输出当前节点
3.2如果当前节点的右子节点不为空,则右子节点递归中序遍历

4.后序遍历思路分析:
先输出左子节点,在输出右子节点,最后输出父节点
步骤
3.1如果当前节点的左子节点不为空,则左子节点递归后序遍历,
3.2如果当前节点的右子节点不为空,则右子节点递归后序遍历
3.3输出当前节点

代码实现

package tree;


public class TreeTest {
    public static void main(String[] args){
        //初始化节点
        HeroNode root = new HeroNode(1,"宋江","及时雨");
        HeroNode hero2 = new HeroNode(2,"吴用","智多星");
        HeroNode hero3 = new HeroNode(3,"李逵","黑旋风");
        HeroNode hero4 = new HeroNode(4,"卢俊义","玉麒麟");
        HeroNode hero5 = new HeroNode(5,"武松","豹子头");

        //初始化二叉树
        BinaryTree tree = new BinaryTree();
        //数中添加节点
        tree.setRoot(root);
        root.setLeft(hero2);
        root.setRight(hero3);
        hero3.setLeft(hero4);
        hero3.setRight(hero5);

        System.out.println("-----------①遍历测试-------------");
        //前序遍历
        System.out.println("--------前序遍历--------");
        tree.preOrder();
        //中序遍历
        System.out.println("--------中序遍历--------");
        tree.infixOrder();
        //后序遍历
        System.out.println("--------后序遍历--------");
        tree.postOrder()
}

//定义一个二叉树
class BinaryTree{
    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("该二叉树没有根节点,无法遍历");
        }
    }
}



//定义一个节点类
class HeroNode{
    private int id;//id
    private String name;//姓名
    private String nickName;//别名
    private HeroNode left;//左节点
    private HeroNode right;//右节点,默认为空


    //无参构造器
    public HeroNode() {

    }


    //有参构造器
    public HeroNode(int id, String name, String nickName) {
        this.id = id;
        this.name = name;
        this.nickName = nickName;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public HeroNode getLeft() {
        return left;
    }

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

    public HeroNode getRight() {
        return right;
    }

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

    //重写toString 不用加左右节点,默认为空
    @Override
    public String toString() {
        return "HeroNode{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +
                '}';
    }

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

    ///中序遍历
    public void infixOrder(){
        //1.左子树递归中序遍历
        if (this.left != null){
            this.left.infixOrder();
        }
        //2.输出父节点
        System.out.println(this);
        //3.右子树递归中序遍历
        if (this.right != null){
            this.right.infixOrder();
        }


    }
    //后续遍历
    public void postOrder(){
        //1.左子树递归后序遍历
        if (this.left != null){
            this.left.postOrder();
        }
        //2.右子树递归后序遍历
        if (this.right != null) {
            this.right.postOrder();
        }
        //3.输出父节点
        System.out.println(this);

    }
}

结果截图
在这里插入图片描述

三、二叉树的前序,中序,后续查找

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

package tree;


public class TreeTest {
    public static void main(String[] args){
        //初始化节点
        HeroNode root = new HeroNode(1,"宋江","及时雨");
        HeroNode hero2 = new HeroNode(2,"吴用","智多星");
        HeroNode hero3 = new HeroNode(3,"李逵","黑旋风");
        HeroNode hero4 = new HeroNode(4,"卢俊义","玉麒麟");
        HeroNode hero5 = new HeroNode(5,"武松","豹子头");

        //初始化二叉树
        BinaryTree tree = new BinaryTree();
        //数中添加节点
        tree.setRoot(root);
        root.setLeft(hero2);
        root.setRight(hero3);
        hero3.setLeft(hero4);
        hero3.setRight(hero5);

        System.out.println("-----------①遍历测试-------------");
        //前序遍历
        System.out.println("--------前序遍历--------");
        tree.preOrder();
        //中序遍历
        System.out.println("--------中序遍历--------");
        tree.infixOrder();
        //后序遍历
        System.out.println("--------后序遍历--------");
        tree.postOrder();


        System.out.println("-----------②查找测试-------------");
        //前序查找编号为5的节点信息
        System.out.println("查找编号为5的节点信息..");
        HeroNode searchHero = tree.preOrderSearch(1);
        if (searchHero != null){
            System.out.printf("查找成功!!节点信息:id=%d,name=%s,nickName=%s\n",searchHero.getId(),searchHero.getName(),searchHero.getNickName());
        }else{
            System.out.printf("查询失败!!没有编号%d的节点信息\n",1);
        }

        //中序查找编号为6的节点信息
        System.out.println("查找编号为6的节点信息..");
        HeroNode curNode = tree.infixOrderSearch(6);
        if (curNode != null){
            System.out.printf("查找成功!!节点信息:id=%d,name=%s,nickName=%s\n",curNode.getId(),curNode.getName(),curNode.getNickName());
        }else{
            System.out.printf("查询失败!!没有编号%d的节点信息\n",6);
        }
        //后续查找编号为5的节点信息
        System.out.println("查找编号为7的节点信息..");
        HeroNode heroNode = tree.postOrderSearch(3);
        if (heroNode != null){
            System.out.printf("查找成功!!节点信息:id=%d,name=%s,nickName=%s\n",heroNode.getId(),heroNode.getName(),heroNode.getNickName());
        }else{
            System.out.printf("查询失败!!没有编号%d的节点信息\n",3);
        }

        System.out.println("-----------③删除测试-------------");
        //删除4号节点
        System.out.println("删除4号节点中.....");
        tree.delNode(4);
        System.out.println("删除后,前序遍历...");
        tree.preOrder();
        System.out.println("删除后,中序遍历...");
        tree.infixOrder();
        System.out.println("删除后,后续遍历...");
        tree.postOrder();

    }
}

//定义一个二叉树
class BinaryTree{
    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;
        }
    }

}



//定义一个节点类
class HeroNode{
    private int id;//id
    private String name;//姓名
    private String nickName;//别名
    private HeroNode left;//左节点
    private HeroNode right;//右节点,默认为空


    //无参构造器
    public HeroNode() {

    }


    //有参构造器
    public HeroNode(int id, String name, String nickName) {
        this.id = id;
        this.name = name;
        this.nickName = nickName;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public HeroNode getLeft() {
        return left;
    }

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

    public HeroNode getRight() {
        return right;
    }

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

    //重写toString 不用加左右节点,默认为空
    @Override
    public String toString() {
        return "HeroNode{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +
                '}';
    }

    //前序查找
    public HeroNode preOrderSearch(int no) {
        System.out.println("查找中~~~~~");
        //1.判断当前节点的no是不是要查找的
        if (this.id == no) {
            return this;
        }
        //定义一个当前节点,用于返回
        HeroNode curNode = null;
        //2.左递归
        if (this.left != null) {
            curNode = this.left.preOrderSearch(no);
        }
        if (curNode != null) {//当前节点不为空,说明找到该节点
            return curNode;
        }
        //3.右递归
        if (this.right != null) {
            curNode = this.right.preOrderSearch(no);
        }
        return curNode;

    }

    //中序查找
    public HeroNode infixOrderSearch(int no) {
        //定义一个当前节点,用于返回
        HeroNode curNode = null;
        //1.左递归
        if (this.left != null) {
            curNode = this.left.infixOrderSearch(no);
        }
        if (curNode != null) {//当前节点不为空,说明找到该节点
            return curNode;
        }

        System.out.println("查找中~~~~~");
        //判断当前节点的no是不是要查找的
        if (this.id == no) {
            return this;
        }

        //右递归
        if (this.right != null) {
            curNode = this.right.infixOrderSearch(no);
        }
        return curNode;

    }


    //后序查找
    public HeroNode postOrderSearch(int no) {
        //定义一个当前节点,用于返回
        HeroNode curNode = null;
        //1.左递归
        if (this.left != null) {
            curNode = this.left.postOrderSearch(no);
        }
        if (curNode != null) {//当前节点不为空,说明找到该节点
            return curNode;
        }

        //右递归
        if (this.right != null) {
            curNode = this.right.postOrderSearch(no);
        }
        if (curNode != null) {
            return curNode;
        }

        System.out.println("查找中~~~~~");
        //判断当前节点的no是不是要查找的
        if (this.id == no) {
            return this;
        }
        return curNode;
    }

  
}

结果截图
在这里插入图片描述

四、二叉树的删除操作

完成删除结点的操作
1)如果刪除的节点是叶子节点,则删除该节点
2)如果删除的节点是非叶子节点,则删除该子树
思路
首先先处理:
如果树是空树root,如果只有一个root结点,则等价将二叉树置空
接着进行下面步骤
1.因为我们的二叉树是单向的,所以我们是判断当前结点的子结点是否需要删除结点,而不能去判断当前这个结点是不是需要删除结点.
2.如果当前结点的左子结点不为空,并且左子结点就是要删除结点,就将this.eft=null;并且就返回(结束递归删除)
3.如果当前结点的右子结点不为空,并且右子结点就是要删除结点,就将this.right=null ;并且就返回(结束递归删除)
4.如果第2和第3步没有删除结点,那么我们就需要向左子树进行递归删除
5.如果第4步也没有删除结点,则应当向右子树进行递归删除.

二叉树全代码

package tree;


public class TreeTest {
    public static void main(String[] args){
        //初始化节点
        HeroNode root = new HeroNode(1,"宋江","及时雨");
        HeroNode hero2 = new HeroNode(2,"吴用","智多星");
        HeroNode hero3 = new HeroNode(3,"李逵","黑旋风");
        HeroNode hero4 = new HeroNode(4,"卢俊义","玉麒麟");
        HeroNode hero5 = new HeroNode(5,"武松","豹子头");

        //初始化二叉树
        BinaryTree tree = new BinaryTree();
        //数中添加节点
        tree.setRoot(root);
        root.setLeft(hero2);
        root.setRight(hero3);
        hero3.setLeft(hero4);
        hero3.setRight(hero5);

        System.out.println("-----------①遍历测试-------------");
        //前序遍历
        System.out.println("--------前序遍历--------");
        tree.preOrder();
        //中序遍历
        System.out.println("--------中序遍历--------");
        tree.infixOrder();
        //后序遍历
        System.out.println("--------后序遍历--------");
        tree.postOrder();


        System.out.println("-----------②查找测试-------------");
        //前序查找编号为5的节点信息
        System.out.println("查找编号为5的节点信息..");
        HeroNode searchHero = tree.preOrderSearch(1);
        if (searchHero != null){
            System.out.printf("查找成功!!节点信息:id=%d,name=%s,nickName=%s\n",searchHero.getId(),searchHero.getName(),searchHero.getNickName());
        }else{
            System.out.printf("查询失败!!没有编号%d的节点信息\n",1);
        }

        //中序查找编号为6的节点信息
        System.out.println("查找编号为6的节点信息..");
        HeroNode curNode = tree.infixOrderSearch(6);
        if (curNode != null){
            System.out.printf("查找成功!!节点信息:id=%d,name=%s,nickName=%s\n",curNode.getId(),curNode.getName(),curNode.getNickName());
        }else{
            System.out.printf("查询失败!!没有编号%d的节点信息\n",6);
        }
        //后续查找编号为5的节点信息
        System.out.println("查找编号为7的节点信息..");
        HeroNode heroNode = tree.postOrderSearch(3);
        if (heroNode != null){
            System.out.printf("查找成功!!节点信息:id=%d,name=%s,nickName=%s\n",heroNode.getId(),heroNode.getName(),heroNode.getNickName());
        }else{
            System.out.printf("查询失败!!没有编号%d的节点信息\n",3);
        }

        System.out.println("-----------③删除测试-------------");
        //删除4号节点
        System.out.println("删除4号节点中.....");
        tree.delNode(4);
        System.out.println("删除后,前序遍历...");
        tree.preOrder();
        System.out.println("删除后,中序遍历...");
        tree.infixOrder();
        System.out.println("删除后,后续遍历...");
        tree.postOrder();

    }
}

//定义一个二叉树
class BinaryTree{
    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("该二叉树没有根节点,无法遍历");
        }
    }



    //前序查找
    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;
        }
    }

    //删除节点
    public void delNode(int no){
        //先判断当前树是否为空树
        if (root != null){
            //只有一个root节点
            if (root.getId() == no){
                root =null;
            }else{
                //root有左右节点,则递归删除
                root.delNode(no);
            }
        }else{
            System.out.println("当前树是空树,不能删除!!");
       }
    }
}



//定义一个节点类
class HeroNode{
    private int id;//id
    private String name;//姓名
    private String nickName;//别名
    private HeroNode left;//左节点
    private HeroNode right;//右节点,默认为空


    //无参构造器
    public HeroNode() {

    }


    //有参构造器
    public HeroNode(int id, String name, String nickName) {
        this.id = id;
        this.name = name;
        this.nickName = nickName;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public HeroNode getLeft() {
        return left;
    }

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

    public HeroNode getRight() {
        return right;
    }

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

    //重写toString 不用加左右节点,默认为空
    @Override
    public String toString() {
        return "HeroNode{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +
                '}';
    }

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

    ///中序遍历
    public void infixOrder(){
        //1.左子树递归中序遍历
        if (this.left != null){
            this.left.infixOrder();
        }
        //2.输出父节点
        System.out.println(this);
        //3.右子树递归中序遍历
        if (this.right != null){
            this.right.infixOrder();
        }


    }
    //后续遍历
    public void postOrder(){
        //1.左子树递归后序遍历
        if (this.left != null){
            this.left.postOrder();
        }
        //2.右子树递归后序遍历
        if (this.right != null) {
            this.right.postOrder();
        }
        //3.输出父节点
        System.out.println(this);

    }

    //前序查找
    public HeroNode preOrderSearch(int no) {
        System.out.println("查找中~~~~~");
        //1.判断当前节点的no是不是要查找的
        if (this.id == no) {
            return this;
        }
        //定义一个当前节点,用于返回
        HeroNode curNode = null;
        //2.左递归
        if (this.left != null) {
            curNode = this.left.preOrderSearch(no);
        }
        if (curNode != null) {//当前节点不为空,说明找到该节点
            return curNode;
        }
        //3.右递归
        if (this.right != null) {
            curNode = this.right.preOrderSearch(no);
        }
        return curNode;

    }

    //中序查找
    public HeroNode infixOrderSearch(int no) {
        //定义一个当前节点,用于返回
        HeroNode curNode = null;
        //1.左递归
        if (this.left != null) {
            curNode = this.left.infixOrderSearch(no);
        }
        if (curNode != null) {//当前节点不为空,说明找到该节点
            return curNode;
        }

        System.out.println("查找中~~~~~");
        //判断当前节点的no是不是要查找的
        if (this.id == no) {
            return this;
        }

        //右递归
        if (this.right != null) {
            curNode = this.right.infixOrderSearch(no);
        }
        return curNode;

    }


    //后序查找
    public HeroNode postOrderSearch(int no) {
        //定义一个当前节点,用于返回
        HeroNode curNode = null;
        //1.左递归
        if (this.left != null) {
            curNode = this.left.postOrderSearch(no);
        }
        if (curNode != null) {//当前节点不为空,说明找到该节点
            return curNode;
        }

        //右递归
        if (this.right != null) {
            curNode = this.right.postOrderSearch(no);
        }
        if (curNode != null) {
            return curNode;
        }

        System.out.println("查找中~~~~~");
        //判断当前节点的no是不是要查找的
        if (this.id == no) {
            return this;
        }
        return curNode;
    }

    //节点删除,因为二叉树是单向的,所以需要判断是当前节点的子节点需要删除
    public void delNode(int no){
        //1.如果当前节点的左子树不为空,并且左子树刚好是待删除节点
        if (this.left != null && this.left.id == no){
            this.left =null;
            return;
        }
        //2.如果当前节点的右子树不为空,并且右子树刚好是待删除节点
        if (this.right != null && this.right.id == no){
            this.right =null;
            return;
        }
        //3.当1,2都不满足,则左子树递归删除
        if (this.left != null){
            this.left.delNode(no);
        }
        //4.当3不满足时,递归删除右子树
        if (this.left != null){
            this.right.delNode(no);
        }

    }
}

删除截图
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值