数据结构(5)树形结构——二叉搜索树(JAVA代码实现)

简介: 5.1.概述二叉搜索树,也叫二叉查找树、二叉排序树,顾名思义,这种二叉树是专门用来进行数据查找的二叉树。二叉搜索树的查找其实就是二分查找。二叉搜索树的定义:二叉搜索树可以为空如果二叉搜索树不为空,那么每个有孩子结点的结点,其左孩子的值一定要小于它,其右孩子的值一定要大于它。

5.1.概述

二叉搜索树,也叫二叉查找树、二叉排序树,顾名思义,这种二叉树是专门用来进行数据查找的二叉树。二叉搜索树的查找其实就是二分查找。

二叉搜索树的定义:

  • 二叉搜索树可以为空
  • 如果二叉搜索树不为空,那么每个有孩子结点的结点,其左孩子的值一定要小于它,其右孩子的值一定要大于它。

二叉搜索树的操作集:

既然是专门用来进行查找的二叉搜索树的操作集自然就是增删查,没有改,因为二叉搜索树中的元素都是排序好的,如果直接就地改动某个节点很可能破坏有序性,所以当发现插入的数据有误的时候先删除,再重新插入,一定要保证数据经过了插入流程,这样数据才会在对的位置,才能保证整棵的有序性。

boolean find(Object target);
Object findMin();
Object findMax();
void insert(Object data);
void delete(Object data);

5.2.操作

5.2.1.节点

节点实体如下:

public class Node {
    //数据域
    private int data;
    //指针域
    private Node left;
    private Node right;
    //遍历标志
    private boolean isOrder;
    {
        isOrder=false;
    }
    public Node(){
    }
    public Node(int data){
        this.data=data;
    }
    public int getData() {
        return data;
    }
    public void setData(int data) {
        this.data = data;
    }
    public Node getLeft() {
        return left;
    }
    public void setLeft(Node left) {
        this.left = left;
    }
    public Node getRight() {
        return right;
    }
    public void setRight(Node right) {
        this.right = right;
    }
    public boolean isOrder() {
        return isOrder;
    }
    public void setOrder(boolean order) {
        isOrder = order;
    }
}

5.2.2.插入

假设插入35,从根节点开始比较,

35>30,属于30的右子树,30的右孩子不为空,继续向下走,

35<41,属于41的左子树,41的左孩子不为空,继续向下走,

35>33,属于33的右子树。33的右孩子为空,35是33的右孩子。

1d309c2f1a0041f3be255215038bdc0c.png

代码示例:

//记录根节点
    private static Node root=null;
    //用于寻路的指针
    private static Node flag=null;
    public static void insert(Node node){
        if(root==null){
            System.out.println("我插入"+node.getData()+"作为根节点");
            root=node;
        }
        flag=root;
        while (node.getData()<flag.getData()){
            if(flag.getLeft()==null) {
                System.out.println("我在"+flag.getData()+"右边插入一个"+node.getData());
                flag.setLeft(node);
            }
            flag = flag.getLeft();
        }
        while(node.getData()>flag.getData()){
            if(flag.getRight()==null) {
                System.out.println("我在"+flag.getData()+"右边插入一个"+node.getData());
                flag.setRight(node);
            }
            flag = flag.getRight();
        }
    }

5.2.3.查找

1.查找某个值是否存在

二叉搜索树的查找其实就是借助数据结构实现了二分查找,如果当前节点的值大于要查找的值,说明要查找的值只可能存在于当前节点的右子树,如果当前节点的值小于要查找的值,说明要查找的值只可能存在于当前节点的左子树。不断重复以上过程,遇见两种情况终止:


当前节点是要查找的值,查找成功,说明值存在。

当前的值不是要查找的值,且节点没有左右子树,是叶子节点,查找失败,说明值不存在。

代码示例:

public static boolean find(int target){
        //从根节点开始
        flag=root;
        while(true){
            //当前节点值为查找值
            if(flag.getData()==target){
                return true;
            }
            //向右子树查找
            if(target>flag.getData()){
                flag=flag.getRight();
            }
            //向左子树查找
            if(target<flag.getData()){
                flag=flag.getLeft();
            }
            //当前节点是叶节点
            if(flag==null){
                return false;
            }
        }
    }

2.查找最大值

从根节点开始一直沿着右子树的右孩子进行查找,右子树的最后一个右孩子一定是最大值。

public static int findMax(){
        flag=root;
        while(flag.getRight()!=null){
            flag=flag.getRight();
        }
        return flag.getData();
    }

3.查找最小值

从根节点开始一直沿着左子树的左孩子进行查找,左子树的最后一个左孩子一定是最小值。

public static int findMin() {
        flag = root;
        while (flag.getLeft() != null) {
            flag = flag.getLeft();
        }
        return flag.getData();
    }

5.2.4.删除

被删除的节点有三种情况

叶子节点,直接删除即可。

只有一个孩子,用孩子节点接替被删除节点即可。

左右孩子双全,用左子树中最大值接替被删除节点,用右子树中最小值接替被删除节点。

代码示例:


二叉搜索树由于是整体有序的,每个元素的变动都会造成一定范围内需要进行整体的重新排序,且排序过程是重复的,因此这个过程用递归实现更加简洁,用循环会很冗长,此处选用递归实现。

public static void delete(int target){
        flag=root;
        //由于删除节点会引起树的调整,为了以防万一根节点需要重新指向一下
        root=doDelete(flag,target);
    }
    private static Node doDelete(Node node,int target){
        //空树直接返回,或者是递归出口1:已经遍历完整棵树
        if(node == null) {
            return null;
        }
        //递归左子树
        if(target < node.getData()) {
            node.setLeft(doDelete(node.getLeft(), target));
        }
        //递归右子树
        if(target > node.getData()) {
            node.setRight(doDelete(node.getRight(), target));
        }
        //执行到此步,说明已经出递归,并且没有走递归出口1返回,说明找到了目标
        //情况1:被删除节点只有一个孩子节点
        //情况2:被删除节点为叶子节点
        //以上两种情况可以合并成一个逻辑处理,即指向自己的孩子节点即可
        if(node.getLeft() == null) {
            return node.getRight();
        }
        if(node.getRight() == null) {
            return node.getLeft();
        }
        //情况3:被删除节点左右孩子双全,找右子树中最小值接替被删除节点,右子树需递归此过程整体做调整
        Node minNode = findMinNode(node.getRight());
        node.setData(minNode.getData());
        node.setRight(doDelete(node.getRight(),minNode.getData()));
        return node;
    }
    private static Node findMinNode(Node node){
        while(node.getLeft() != null)
            node = node.getLeft();
        return node;
    }


目录
打赏
0
0
0
0
22
分享
相关文章
|
22天前
|
算法系列之数据结构-二叉搜索树
二叉查找树(Binary Search Tree,简称BST)是一种常用的数据结构,它能够高效地进行查找、插入和删除操作。二叉查找树的特点是,对于树中的每个节点,其左子树中的所有节点都小于该节点,而右子树中的所有节点都大于该节点。
62 22
【数据结构】二叉搜索树(二叉排序树)
本文介绍了二叉搜索树(Binary Search Tree, BST)的定义、实现及其性能分析。二叉搜索树是一种特殊的二叉树,其特点是左子树所有节点值小于根节点值,右子树所有节点值大于根节点值,且每个子树也满足此特性。文中详细讲解了BST的节点结构、插入、查找、删除等操作的实现,并通过C++代码展示了这些功能。此外,还讨论了BST的性能:在理想情况下,时间复杂度接近O(logN),但在最坏情况下可能退化为O(N)。为了提高效率,后续将学习自平衡二叉搜索树如AVL树和红黑树。掌握BST有助于理解STL中的set和map容器。感谢阅读,欢迎点赞支持。
43 9
|
5月前
|
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
70 1
解锁“分享文件”高效密码:探秘 Java 二叉搜索树算法
在信息爆炸的时代,文件分享至关重要。二叉搜索树(BST)以其高效的查找性能,为文件分享优化提供了新路径。本文聚焦Java环境下BST的应用,介绍其基础结构、实现示例及进阶优化。BST通过有序节点快速定位文件,结合自平衡树、多线程和权限管理,大幅提升文件分享效率与安全性。代码示例展示了文件插入与查找的基本操作,适用于大规模并发场景,确保分享过程流畅高效。掌握BST算法,助力文件分享创新发展。
Java 集合江湖:底层数据结构的大揭秘!
小米是一位热爱技术分享的程序员,本文详细解析了Java面试中常见的List、Set、Map的区别。不仅介绍了它们的基本特性和实现类,还深入探讨了各自的使用场景和面试技巧,帮助读者更好地理解和应对相关问题。
79 5
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
88 6
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
Java 中常用的数据结构
【10月更文挑战第20天】这些数据结构在 Java 编程中都有着广泛的应用,掌握它们的特点和用法对于提高编程能力和解决实际问题非常重要。
73 6
Java中的Map接口提供了一种优雅的方式来管理数据结构,使代码更加清晰、高效
【10月更文挑战第19天】在软件开发中,随着项目复杂度的增加,数据结构的组织和管理变得至关重要。Java中的Map接口提供了一种优雅的方式来管理数据结构,使代码更加清晰、高效。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,帮助开发者告别混乱,提升代码质量。
57 1
编写Java程序,以树形结构显示国家-直辖市/省/州信息
编写Java程序,以树形结构显示国家-直辖市/省/州信息
365 0
编写Java程序,以树形结构显示国家-直辖市/省/州信息
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等