数据结构与算法——二叉树详解java

本文详细介绍了二叉树的定义、特性以及在数据结构中的优势。通过Java实现二叉树的查找、插入、删除操作,分析了二叉树的效率,包括查找、插入和删除的时间复杂度。此外,还探讨了不同类型的遍历方法,如中序、前序和后序遍历。

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

我们有序数组查找快,可以通过二分查找快速的查找到数据,但是要在有序数组中插入一个数的话,就必须先找到插入数据项的位置,然后将所有插入位置后面的数据项后移以为,给新的数据腾出空间,同时删除数据也是一样的道理,可以知道这样的话是很浪费时间的,
同时另外的一种数据结构——链表,链表的插入和删除很快,我们只需要改变一些引用,但是查找数据就会很慢,因为我们无论查找到什么数据,都需要从链表的第一个数据开始,遍历找到所有的数据项位置,
今天说到的树也是一种数据结构,同时具备数组查找快和链表的插入与删除的优点

树是一种抽象数据类型,用来模拟具有树状结构性质的数据集合,它是由n(n>0)个有限节点通过连接他们的边组成的层次集合,但是我们今天的树看起来会像一颗倒挂的树,也就是说它的根在上面,而叶子在下面
在这里插入图片描述 1. 节点:就是上面的圆圈,节点一般代表的是实体,在java的面向对象中,节点一般代表的是对象
2. 边:边就是连接节点的线,便表示节点的关联关系,一遍是从一个节点到另一个节点,也就是说一个节点到下一个节点的唯一方法就是顺着这个边前进,在java中相当于引用
树有很多种,像上面的一个节点有多余的两个子节点的树,称为多路树,而每个节点最多只有两个节点的一种形式成为二叉树,也是本章博客的重点

树的常用语

在这里插入图片描述1. 路劲:顺着节点的边从一个节点到另一个节点,所经过的节点的顺序排列称为 路径
2. 根: 树的顶端的节点称为根节点,一棵树只有一个根,如果要把一个节点和边的集合称为树,那么从根到其他的任意一个节点都必须有且只有一条路径,A就是根节点
3. 父节点: 若一个节点含有子节点,则这个节点称为其子节点的父节点,上面说到的B就是D,E的父节点
4. 子节点:一个子节点含有子树的根节点称为该节点的子节点 D是B的子节点
5. 兄弟节点: 具有相同父节点的节点称为兄弟节点,上面说的就是 D,E为兄弟节点
6. 叶节点: 没有子节点的节点称为叶节点,上面图中的H就是叶节点
7. 子树: 每个节点都可以作为子树的根,它和它所有的子节点、子节点的子节点等都包含在子树中。
8. 节点的层次: 从根节点定义,根为第一层,根的子节点为第二层,以此类推
9. 深度: 对于任意节点n,n的深度为从根到n的唯一路径长,根的深度为0;
10. 高度: 对于任意节点n,n的高度为从n到一片树叶的最长路径长,所有树叶的高度为0;

二叉树

二叉树: 树的每个节点最多只有两个节点
二叉树若它的左子树不为空,那么左子树所有的节点均小于它的根值,若它的右子树不为空,则右子树上的所有节点均大于它的根节点,它的左,右子树也分为二叉排序树
在这里插入图片描述

二叉树的节点类
package com.example.study;

/**
 * @author wangchunguang
 * @version $Id:
 * @date 2018/12/19 23:11
 */

public class Node {
   
   
    private Object date;//节点数据
    private Node leftChild;//左子节点的引用
    private Node rightChild;//右子节点的引用
//    打印节点的数据
    public void  disPlay(){
   
   
        System.out.println(date);
    }

}

查找节点

查找节点我们都是必须从根部进行遍历

  1. 查找值比当前节点大,则搜索右子树
  2. 查找值比当前的值小,则搜索左子树
  3. 查找值等于当前值,则停止搜索
   //    表示根节点
    private Node root;

    @Override
    public Node find(int key) {
   
   
        Node current = root;
//        先判断节点是否为空
        while (current != null) {
   
   
            if (current.data > key) {
   
   //当前值比查找的值大  就搜索左子树
                current = current.leftChild;
            } else if (current.data < key) {
   
   //当前值比查找值小 搜索右子树
                current = current.rightChild;
            } else {
   
   
                return current;
            }
        }
        return null;//遍历结束整个树  都没有找到 返回null
    }

用变量current来保存当前查找的节点,参数key表示要查找的值,刚开始将根节点赋值到current,在循环中,将要查找的值和current保存的节点进行对比,如果key小于当前节点,则搜索当前节点的左子节点,如果大于就搜索右子节点,如果等于的话 就返回当前节点,如果不存在的话就直接返回null
树的效率: 查找节点的时间取决于这节点所在的层次,每一层最多有2n-1个节点,总共N层共有2n-1个节点,那么时间复杂度为O(logn),底数为2。

插入节点

要插入节点,必须要找到插入位置,与查找类似,由于二叉搜索树的特殊性,待插入节点也需要从根节点上面进行比较,小于则与根节点的左子树进行比较,反之则与右子树比较,直到左子树为空或者右子树为空,则插入到相应的位置,比较过程中要注意保存父节点的信息,以及带插入位置是父节点的左子树还是右子树,才能插入正确的位置

  // 插入节点
    @Override
    public boolean insert(int dara) {
   
   
        Node newNode = new Node(dara);
        if (root == null) {
   
   //当前树为空树,没有任何节点
            root = newNode;
            return true;
        } else {
   
   
            Node current = root;
            Node parentNode = null;
            while (current != null) {
   
   
                parentNode = current;
                if (current.data > dara) {
   
   //当前值比插入值大,搜索左子节点
                    current = current.leftChild;
                    if (current == null) {
   
   //左子节点为空,直接将新值插入到该节点
                        parentNode.leftChild = newNode;//插入节点
                        return true;
                    }
                } else {
   
   
                    current = current.rightChild;
                    if (current == null) {
   
   //右子节点为空,直接将新值插入到该节点
                        parentNode.rightChild = newNode;//插入节点
                        return true;
                    }
                }
            }
        }

        return false;
    }

遍历树

遍历树是根据一种特定的顺序访问树的每一个节点,常用的有前序遍历,中序遍历和后续遍历,而二叉搜索树最常用的是中序遍历

  1. 中序遍历:左子树——》根节点——》右子树
    在这里插入图片描述B-D-C-E-A-L-F-N-Q-M
    解释先中序遍历A的左子树(BCDE,B没有左子树,遍历根B,然后右子树CDF,先遍历左子树D,然后根节点C,右子数E),然后是主根节点A,最后是右子树(FLMLNLQ,左子数为L,根F,右子树MNQ,先左子树NQ,N无左子树,先根N,后Q,最后M)
    // 中序遍历
    public static void infixOrder(Node current) {
   
   
        if (current != null) {
   
   
            infixOrder(current.leftChild);
            System.out.print(current.data + " ");
            infixOrder(current.rightChild);
        }
    }
  1. 前序遍历: 根节点——》左子树——》右子树
    在这里插入图片描述A-B-D-C-E-F-G
    解释:先访问根节点A,然后访问A的左子树(包括BD,把分支BD当成一个整体,在先序访问根节点B,然后访问B的左子数D),最后访问A的右子数(包括CEFG,把它们看成一个整体,先访问C,在访问C的左子树E,然后访问C的右子数FG,先访问根节点F,然后左子数G)
 //  前序遍历
    public 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值