树形数据结构-二分搜索树Binary Search Tree

什么是Binary Search Tree数据结构?
它是一种搜索树,一种已排序的数据结构,通常用于存储动态集或键为字符串的关联数组。
二叉搜索树(Binary Search Tree),也称二叉查找树。如果你看见有序二叉树(Ordered Binary tree)、排序二叉树(Sorted Binary Tree)那么说的都是一个东西。
在这里插入图片描述
具有以下的特点
1:若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
2:若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
3:任意节点的左、右子树也分别为二叉查找树;
类似这样的开发中用到的二叉树场景,都是基于配置生成,所以组合出来的节点也更加方便控制树高和平衡性。这与 Java API HashMap 中的红黑树这样为了解决插入节点后仍保持树的平衡性是有所不同的。
所以二叉搜索树也是一颗没有经过调衡的基础性数据结构,在一定概率上它完成有可能退化成链表,也就是从近似O(logn)的时间复杂度退化到O(n)。关于二叉搜索树的平衡解决方案,包括;AVL树、2-3树、红黑树等
以下是实战部分
1:树枝的定义
在这里插入图片描述
用于组成一颗树的节点,则需要包括;值和与之关联的三角结构,一个父节点、两个孩子节点。如果是AVL树还需要树高,红黑树还需要染色标记。
2:插入方法实现

public Node insert(int e) {
        // 缓存
        elementList.add(e);
        if (null == root) {
            root = new Node(this.getClass(), e, null, null, null);
            size++;
            return root;
        }
        // 索引出待插入元素位置,也就是插入到哪个父元素下
        Node parent = root;
        Node search = root;
        while (search != null && search.value != null) {
            parent = search;
            if (e < search.value) {
                search = search.left;
            } else {
                search = search.right;
            }
        }
        // 插入元素
        Node newNode = new Node(this.getClass(), e, parent, null, null);
        if (parent.value > newNode.value) {
            parent.left = newNode;
        } else {
            parent.right = newNode;
        }

        size++;
        return newNode;
    }

A:首先判断插入元素时候是否有树根,没有则会把当前节点创建出一颗树根来。
B:如果当前树是有树根的,则对插入元素与当前树进行一个节点遍历操作,找到元素可以插入的索引位置 parent(挂到这个父节点下)。也就是 search 搜索过程。
C:最后就是插入元素,通过给插入值创建一个 Node 节点,并绑定它的父元素,以及把新元素挂到索引到的 parent 节点下。
3:索引节点
在这里插入图片描述
值查找的过程,就是对二叉搜索树的遍历,不断的循环节点,按照节点值的左右匹配,找出最终相当的值节点。
4:删除节点

 protected Node delete(Node delNode) {
        if (delNode == null) return null;
        Node result = null;
        if (delNode.left == null) {
            result = transplant(delNode, delNode.right);
        } else if (delNode.right == null) {
            result = transplant(delNode, delNode.left);
        } else {
            // 因为删除的节点,有2个孩子节点,这个时候找到这条分支下,最左侧做小的节点。用它来替换删除的节点
            Node miniNode = getMiniNode(delNode.right);
            if (miniNode.parent != delNode) {
                // 交换位置,用miniNode右节点,替换miniNode
                transplant(miniNode, miniNode.right);
                // 把miniNode 提升父节点,设置右子树并进行挂链。替代待删节点
                miniNode.right = delNode.right;
                miniNode.right.parent = miniNode;
            }
            // 交换位置,删除节点和miniNode 可打印测试观察;System.out.println(this);
            transplant(delNode, miniNode);
            // 把miniNode 提升到父节点,设置左子树并挂链
            miniNode.left = delNode.left;
            miniNode.left.parent = miniNode;
            result = miniNode;
        }
        size--;
        return result;
    }

    protected Node getMiniNode(Node node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }

    /**
     * 节点替换
     *
     * @param delNode 删除节点
     * @param addNode 替换节点
     */
    protected Node transplant(Node delNode, Node addNode) {
        if (delNode.parent == null) {
            this.root = addNode;
        }
        // 判断删除元素是左/右节点
        else if (delNode.parent.left == delNode) {
            delNode.parent.left = addNode;
        } else {
            delNode.parent.right = addNode;
        }
        // 设置父节点
        if (null != addNode) {
            addNode.parent = delNode.parent;
        }
        return addNode;
    }

5:删除单节点
在这里插入图片描述
待删除节点14,判断此节点的父节点的孩子节点,哪个等于14,找出左右
把待删节点的右孩子节点,挂到删除节点的右节点
给待删节点的右孩子节点,设置上父节点
6:删除双节点
在这里插入图片描述
待删除节点64,含有双子节点,则需要根据第一个右子节点查找最小左子节点。从89到72,如果有比72还小的左子节点,继续排查。
排查到节点72,将72这个准备替换待删元素的节点,与右子节点73进行位置交换,过程与 4.1 相同。使用交换函数 transplant
最后是进行节点72与待删节点64的交换过程,更换三角关系,父节点、左子节点、右子节点。
测试搜索树
在这里插入图片描述
最后附上经典面试题。
二叉搜索树的插入、删除、索引的时间复杂度
二叉搜索树删除含有双子节点的元素过程叙述
二叉搜索树的节点都包括了哪些信息
为什么Java HashMap 中说过红黑树而不使用二叉搜索树
友友们在评论区写下你们的答案!
以上的是树形数据结构-二分搜索树Binary Search Tree若需完整代码 可识别二维码后 给您发代码。
在这里插入图片描述

  • 20
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值