美文网首页
二叉搜索树

二叉搜索树

作者: Franck_ | 来源:发表于2021-01-20 10:19 被阅读0次

BST

任意一个节点的值,都大于其左子树所有节点的值。
任意一个节点的值,都小于其右子树所有节点的值。
左右子树也是一颗二叉搜索树。

元素必须是可比较的。
元素不能为null 。

类设计:

属性:

树是由一个一个节点组成,那么可以使用一个基础的集合来保存Node。 实际上比不需要一个集合来保存。 只需要记录一个根节点属性就可以了。 节点里面有子节点的指向,就可以根据节点的左右子节点来找到相应的节点了。 所以,第一个属性是根节点。

Node<E> root;

既然有了节点,肯定需要记录下来当前树的大小,那么就会有一个size属性。

int size;

二叉搜索树也是用来保存数据的,所以,必须要有一个元素(数据)的属性。
还是有些不理解,元素直接放在节点里面不就可以了? 为什么还需要一个元素属性?一棵树里面有一个元素????

E element;

为了让二叉树可以存储任何类型的元素,所以可以在类定义的时候加一个泛型。

方法:

提供数据结构应该要有的基础的操作方法:
int size() 返回当前大小
boolean isEmpty() 返回当前是否为空
void clear() 清空当前结构
void add(E element) 添加一个元素
void remove(E element) 删除一个元素
boolean contains(E element) 判断一个元素是否存在

看回节点,因为节点只提供给本类使用,所以创建一个内部类(Node)就可以了。
节点应该也可以存储任何类型的元素,所以定义的时候也可以给一个泛型。

二叉树里面,一个节点都会有父节点和左右子节点(除了根节点没有父节点)。
除此之外,节点应该可以保存一个对象,作为节点的数据。

所以, 内部类如下:


    private static class Node<E>{

        E element;    
        Node<E> left;
        Node<E> right;
        Node<E> parent;

        //构造函数,因为parent是除了根节点以外其他节点都必须有的,所以构造函数要提供。 left和right每个节点不一定有,所以不需要在构造函数里面提供。
        public Node(E element, Node<E> parent) {
            this.element = element;
            this.parent = parent;
        }

    }

整合上述,整个二叉搜索树的基础结构如下:

二叉搜索树基础结构

package com.franck.dateStruct.tree;

/**
 * 二叉搜索树
 */
public class BinarySearchTree<E> {

    private int size;

    private E element;

    /**
     * 返回当前大小
     * @return size
     */
    public int size() {
        return size;
    }

    /**
     * 返回当前是否为空
     * @return 是否为空
     */
    public boolean isEmpty() {
        return size == 0 ;
    }

    /**
     *    清空所有元素
     */
    public void clear() {

    }

    /**
     * 添加一个元素
     * @param element 元素
     */
    public void add(E element) {

    }

    /**
     * 删除一个特定元素
     * @param element 需要删除的元素
     */
    public void remove(E element) {
        
    }

    /**
     * 判断元素是否存在
     * @param element 需要判断的元素
     * @return 判断结果
     */
    public boolean contains(E element) {
        return false;
    }


    private static class Node<E>{

        E element;
        Node<E> left;
        Node<E> right;
        Node<E> parent;

        public Node(E element, Node<E> parent) {
            this.element = element;
            this.parent = parent;
        }

    }

}

实现比较方法:

二叉搜索树的元素一定是可比较的。

1 继承compareable接口。

2 使用比较器。

3 使用比较器 + comparable接口。

实现添加方法:

1 非空检测

不能将null添加到数里面,所以首先要进行非空的检测。在这边,写一个非空检测的方法,因为其他的方法也会用到非空检测,所以抽出来做成一个方法。在添加方法的第一步,调用检测方法。


   /**
     * 添加一个元素
     * @param element 元素
     */
    public void add(E element) {
        elementNotNullCheck(element);
        
    }   
    
    private void elementNotNullCheck(E element) {
        if (element == null) {
            throw new IllegalArgumentException("元素不能为null");
        }
    }

2 添加根节点

如果根节点为null,则先添加根节点。

    public void add(E element) {
        elementNotNullCheck(element);

        if (this.root == null) {
            root = new Node<E>(element,null);
            size++;
            return ;
        }
    }

3 添加子节点

如果根节点不是null,则当前一定是添加子节点。
实现思路

  1. 找到新增节点的父节点。
    从根节点开始对比,如果比根节点大,则去右子树找,如果比根节点小,则去左子树找。一直找到空的位置。如果新增的节点和父节点相等,不处理,或者替换,建议进行替换。因为新元素和旧元素是不一样的。如果没有处理,则丢失了新增的节点了。

  2. 确定新增节点的位置。
    确定父节点后,也就确定了新增节点的位置,是父节点的左节点还是右节点,还是和父节点一样。 然后新增加一个节点,添加进树里面。 然后设置新增的节点为父节点的左子树或者右子树,或者替换掉父节点。

下面是增加添加子节点的逻辑代码(JDK的实现会更复杂一些,会使用到比较器来实现更加灵活的元素的比较,这里只使用comparable来比较):

    /**
     * 添加一个元素
     * @param element 元素
     */
    public void add(E element) {
        elementNotNullCheck(element);

        if (this.root == null) {
            root = new Node<E>(element,null);
            size++;
            return ;
        }

        Node<E> parent = root;
        Node<E> current = root;

        int result = 0;

        while (current != null) {
            parent = current;

            result = element.compareTo(current.element);

            if (result < 0) {
                //左节点
                current = current.left;
            } else if (result > 0) {
                //右节点
                current = current.right;

            } else {
                //相等
                current.element = element;
            }

        }

        //创建节点
        Node<E> newNode = new Node<E>(element,parent);

        //设置节点的位置
        if (result < 1) {
            parent.left = newNode;
        } else if (result > 1) {
            parent.right = newNode;
        }
        size++;
    }

   private void elementNotNullCheck(E element) {
        if (element == null) {
            throw new IllegalArgumentException("元素不能为null");
        }
    }

相关文章

  • 数据结构与算法之二叉搜索树(八)

    目录 二叉搜索树概念二叉搜索树的接口设计,包括增,删,改,查平衡二叉搜索树 一 二叉搜索树 二叉搜索树是二叉树的一...

  • Algorithm小白入门 -- 二叉搜索树

    二叉搜索树二叉搜索树 BSTBST 的基本操作计算合法的 BST 1. 二叉搜索树 BST 二叉搜索树(Binar...

  • 二叉搜索树

    二叉搜索树 图解二叉树搜索算法图解:二叉搜索树算法二叉查找树(Binary Search Tree),(又:二叉搜...

  • 23-红黑树

    1.二叉搜索树(BST)继承二叉树(BinaryTree) 2.平衡二叉搜索树(BBST)继承二叉搜索树(BST)...

  • 二叉搜索树(Binary Search Tree)

    1. 定义 二叉搜索树(BST)又叫二叉查找树,二叉排序树。二叉搜索树就是一棵二叉树,但是它又具有搜索树的特征: ...

  • 二叉树基础

    二叉树的分类 完全二叉树与满二叉树 二叉搜索树BST 平衡二叉搜索树BBST因为二叉搜索树有可能退化为链表,降低查...

  • 数据结构 经典算法复习

    二叉搜索树, 平衡二叉树(AVL) 红黑树 B树(平衡多路搜索树) B+树(在B树上改造) 二叉搜索树...

  • Swift 验证二叉搜索树- LeetCode

    题目: 验证二叉搜索树 验证二叉搜索树给定一个二叉树,判断其是否是一个有效的二叉搜索树。 假设一个二叉搜索树具有...

  • 树,二叉树,搜索树

    树,二叉树,搜索树 资料 二叉搜索树 Demo 树的遍历 Demo 题目 ◎ 二叉树的中序遍历 ◎ 二叉树...

  • 【数据结构】红黑树

    1、什么是红黑树? 红黑树是一个要求不那么严格的平衡二叉树搜索树(平衡二叉搜索树/AVL树=平衡二叉树+二叉搜索树...

网友评论

      本文标题:二叉搜索树

      本文链接:https://www.haomeiwen.com/subject/uoqfoktx.html