Java learning diary data structure and algorithm: binary sort tree

Binary Sort Tree

Binary Sort Tree (Binary Sort Tree), also known as Binary Search Tree, also known as Binary Search Tree. It is a type of data structure. In general, query efficiency is higher than linked list structure.

Definition of binary sort tree :

  • When the left subtree is not empty, all node values ​​on the left subtree are less than the root node value of the left subtree

  • When the right subtree is not empty, all node values ​​on the right subtree are less than the root node value of the right subtree

  • If there are nodes with the same value in the binary tree, it can be placed in its left child node or right child node (if it is not needed for development, try not to have nodes with the same value)

 

Insert operation

step:

(1)  Determine whether the root node is empty, if it is empty, set the inserted node as the root node

(2.1)  Determine whether the inserted node value is less than the current node value, and if it is less, go to the left node

(2.2)  When going to the left node, judge whether the left node is empty, if it is empty, set the left node as an insert node, if it is not empty, skip to step (2)

(3.1)  Judge whether the value of the inserted node is greater than the value of the current node, if it is greater, go to the right node

(3.2)  When going to the right node, judge whether the right node is empty, if it is empty, set the right node as an insert node, if it is not empty, skip to step (2)

The following figure is an illustration of the process of inserting the [6, 2, 7, 1, 4, 8] array into the binary sort tree in order:

Code

BSTNode root;//二叉排序树的根节点

public void add(BSTNode node){
    //如果根节点为空则,则将传入节点设置为根节点
    if (root == null){
        root = node;
    }else {
        add(node, root);
    }
}

/**
 * 在二叉排序树中添加节点
 * @param node 添加的节点
 * @param pointer 辅助指针节点,初始指向根节点
 */
public void add(BSTNode node, BSTNode pointer){
    if (node == null){
        return;
    }

    if (pointer.value > node.value){//指针节点值大于添加节点值时
        //如果指针节点的左节点刚好为空,则将添加节点插入到该左节点
        if (pointer.left == null){
            pointer.left = node;
        }else {
            //如果不是则继续往左节点走
            add(node, pointer.left);
        }
    }else {//指针节点值小于添加节点值时
        //如果指针节点的右节点刚好为空,则将添加节点插入到该右节点
        if (pointer.right == null){
            pointer.right = node;
        }else {
            //如果不是则继续往右节点走
            add(node, pointer.right);
        }
    }
}

Find operation

step:

(1)  Determine whether the current node is a search node, and if so, return to the current node directly

(2)  Judge whether the current node value is greater than the search node value, if it is greater than the left node search, skip to step (1)

(3)  Judge whether the current node value is less than the search node value, if it is less, go to the right node to search, skip to step (1)

The following figure is an illustration of finding a node with a value of 4 from the binary sort tree:

Code

//根据value值查找节点
public BSTNode searchNode(int value){
    if (root == null){
        return null;
    }
    return searchNode(value, root);
}

/**
 * 根据value值查找节点
 * @param value 查找的节点
 * @param node 查找的树
 * @return
 */
public BSTNode searchNode(int value, BSTNode node){
    //如果当前节点的值等于value时,则返回该节点
    if (node.value == value) {
        return node;
    } else if (node.value > value){//当前节点的值大于value时
        //如果该节点的左节点为空,则表示二叉排序树内没有该值的节点,返回空
        if (node.left == null)
            return null;
        //左节点不为空,继续往左子树查找
        return searchNode(value, node.left);
    }else {//当前节点的值小于value时
        //如果该节点的右节点为空,则表示二叉排序树内没有该值的节点,返回空
        if (node.right == null)
            return null;
        //右节点不为空,继续往右子树查找
        return searchNode(value, node.right);
    }
}

Delete operation

There are 3 possible states to delete a node:

  • The deleted node is a leaf node

  • Delete node only the left subtree is empty or the right subtree is empty

  • Delete node left subtree and right subtree are empty

step:

(1)  Determine whether the value of the deleted node is less than the value of the current node, if it is less, go to the left node

(2)  Determine whether the value of the deleted node is greater than the value of the current node, if it is greater, go to the right node

(3)  When the value of the deleted node is equal to the value of the current node, that is, the node to be deleted at the current node, determine what state the current node is

(3.1) When the  current node is a leaf node, delete the current node directly

(3.2)  When the left subtree of the current node is empty, place the right node on top to replace the current node position

(3.3)  When the right subtree of the current node is empty, place the left node on top to replace the current node position

(3.4)  When the left subtree and right subtree of the current node are not empty, the maximum value node of the left subtree is removed and deleted, and the maximum value node is used to replace the current node position

Code

/**
 * 根据value值删除节点
 * 删除节点可能有的3种状态:
 * 1.该节点是叶子节点
 * 2.该节点只有左子树或只有右子树
 * 3.该节点左子树和右子树都有
 * @param value 要删除节点的value值
 */
public BSTNode delete(int value, BSTNode node){
    if (value < node.value){//当查找节点值小于当前节点值
        //向左子树递归遍历,并将删除后的新的左子树连接到左节点位置代替原先左子树
        node.left = delete(value, node.left);
        //返回删除后新的树
        return node;
    }else if(value > node.value){//当查找节点值大于当前节点值
        //向右子树递归遍历,并将删除后的新的右子树连接到右节点位置代替原先右子树
        node.right = delete(value, node.right);
        //返回删除后新的树
        return node;
    }else {//当查找节点值等于当前节点值时,即当前节点就是要删除的节点
        //删除节点时叶子节点的状态
        if (node.left == null && node.right == null){
            //直接将该节点设为空
            return null;
        }
        //删除节点左子树为空,右子树不为空的状态
        else if (node.left == null && node.right != null){
            //保存删除节点的右子树
            BSTNode rightSubTree = node.right;
            //将删除节点的右子树设为空,使得该节点能够尽早被垃圾回收
            node.right = null;
            //返回删除节点的右子树,连接到删除节点的父节点
            return rightSubTree;
        }
        //删除节点右子树为空,左子树不为空的状态
        else if (node.right == null && node.left != null){
            BSTNode leftSubTree = node.left;
            node.left = null;
            return leftSubTree;
        }
        //删除节点的左子树和右子树都不为空的状态
        //这里我们使用的是左子树的最大值节点代替的方法
        else {
            //获取左子树的最大值节点并从左子树中删除它
            BSTNode max = max(node.left);
            //将该最大值节点的左子树和右子树设置为该节点的左子树和右子树
            max.left = delMax(node.left);
            max.right = node.right;
            //将删除节点的左子树和右子树设为空,使得该节点能够尽早被垃圾回收
            node.left = null;
            node.right = null;
            //执行完删除操作后,返回以最大值节点为根节点的新的树,连接的删除节点的父节点
            return max;
        }
    }
}

/**
 * 查找传入节点树下value值最大的节点并删除该节点
 * @param node
 * @return
 */
public BSTNode delMax(BSTNode node){
    if (node.right != null){
        node.right = delMax(node.right);
        return node;
    }else {
        BSTNode leftSubTree = node.left;
        node.left = null;
        return leftSubTree;
    }
}
/**
 * 查找传入节点树下value值最大的节点并放回该节点
 * 在二叉排序树中最大值的节点就是最右叶子节点
 * @param node
 * @return
 */
public BSTNode max(BSTNode node){
    BSTNode max = node;
    while (max.right != null){
        max = max.right;
    }
    return max;
}

Complete code

public class BinarySortTreeDemo {
    public static void main(String[] args) {
        int array[] = {13,7,8,3,29,6,1};
        BinarySortTree binarySortTree = new BinarySortTree();
        for (int i=0; i<array.length; i++){
            binarySortTree.add(new BSTNode(array[i]));
        }
        binarySortTree.midOrder();

        System.out.println("删除后二叉顺序树的节点:");
        binarySortTree.delete(13);
        binarySortTree.delete(7);
        binarySortTree.delete(1);
        binarySortTree.delete(29);
        binarySortTree.delete(6);

        binarySortTree.midOrder();
    }
}

//二叉排序树
class BinarySortTree{
    BSTNode root;

    public void setRoot(BSTNode root){
        this.root = root;
    }

    //添加节点
    public void add(BSTNode node){
        //如果根节点为空则,则将传入节点设置为根节点
        if (root == null){
            root = node;
        }else {
            add(node, root);
        }
    }

    /**
     * 在二叉排序树中添加节点
     * @param node 添加的节点
     * @param pointer 指针节点,初始指向根节点
     */
    public void add(BSTNode node, BSTNode pointer){
        if (node == null){
            return;
        }

        if (pointer.value > node.value){//指针节点值大于添加节点值时
            //如果指针节点的左节点刚好为空,则将添加节点插入到该左节点
            if (pointer.left == null){
                pointer.left = node;
            }else {
                //如果不是则继续往左节点走
                add(node, pointer.left);
            }
        }else {//指针节点值小于添加节点值时
            //如果指针节点的右节点刚好为空,则将添加节点插入到该右节点
            if (pointer.right == null){
                pointer.right = node;
            }else {
                //如果不是则继续往右节点走
                add(node, pointer.right);
            }
        }
    }

    //根据value值查找节点
    public BSTNode searchNode(int value){
        if (root == null){
            return null;
        }
        return searchNode(value, root);
    }

    /**
     * 根据value值查找节点
     * @param value 查找的节点
     * @param node 查找的树
     * @return
     */
    public BSTNode searchNode(int value, BSTNode node){
        //如果当前节点的值等于value时,则返回该节点
        if (node.value == value) {
            return node;
        } else if (node.value > value){//当前节点的值大于value时
            //如果该节点的左节点为空,则表示二叉排序树内没有该值的节点,返回空
            if (node.left == null)
                return null;
            //左节点不为空,继续往左子树查找
            return searchNode(value, node.left);
        }else {//当前节点的值小于value时
            //如果该节点的右节点为空,则表示二叉排序树内没有该值的节点,返回空
            if (node.right == null)
                return null;
            //右节点不为空,继续往右子树查找
            return searchNode(value, node.right);
        }
    }


    public void delete(int value){
        //判断删除节点在二叉排序树中是否存在
        BSTNode node = searchNode(value);
        if (node == null){
            throw new RuntimeException("二叉排序树内无对应节点");
        }
        //将删除后新的二叉排序树更换掉原先二叉排序树
        root = delete(value, root);
    }

    /**
     * 根据value值删除节点
     * 删除节点可能有的3种状态:
     * 1.该节点是叶子节点
     * 2.该节点只有左子树或只有右子树
     * 3.该节点左子树和右子树都有
     * @param value 要删除节点的value值
     */
    public BSTNode delete(int value, BSTNode node){
        if (value < node.value){//当查找节点值小于当前节点值
            //向左子树递归遍历,并将删除后的新的左子树连接到左节点位置代替原先左子树
            node.left = delete(value, node.left);
            //返回删除后新的树
            return node;
        }else if(value > node.value){//当查找节点值大于当前节点值
            //向右子树递归遍历,并将删除后的新的右子树连接到右节点位置代替原先右子树
            node.right = delete(value, node.right);
            //返回删除后新的树
            return node;
        }else {//当查找节点值等于当前节点值时,即当前节点就是要删除的节点
            //删除节点时叶子节点的状态
            if (node.left == null && node.right == null){
                //直接将该节点设为空
                return null;
            }
            //删除节点左子树为空,右子树不为空的状态
            else if (node.left == null && node.right != null){
                //保存删除节点的右子树
                BSTNode rightSubTree = node.right;
                //将删除节点的右子树设为空,使得该节点能够尽早被垃圾回收
                node.right = null;
                //返回删除节点的右子树,连接到删除节点的父节点
                return rightSubTree;
            }
            //删除节点右子树为空,左子树不为空的状态
            else if (node.right == null && node.left != null){
                BSTNode leftSubTree = node.left;
                node.left = null;
                return leftSubTree;
            }
            //删除节点的左子树和右子树都不为空的状态
            //这里我们使用的是左子树的最大值节点代替的方法
            else {
                //获取左子树的最大值节点并从左子树中删除它
                BSTNode max = max(node.left);
                //将该最大值节点的左子树和右子树设置为该节点的左子树和右子树
                max.left = delMax(node.left);
                max.right = node.right;
                //将删除节点的左子树和右子树设为空,使得该节点能够尽早被垃圾回收
                node.left = null;
                node.right = null;
                //执行完删除操作后,返回以最大值节点为根节点的新的树,连接的删除节点的父节点
                return max;
            }
        }
    }

    /**
     * 查找传入节点树下value值最大的节点并删除该节点
     * @param node
     * @return
     */
    public BSTNode delMax(BSTNode node){
        if (node.right != null){
            node.right = delMax(node.right);
            return node;
        }else {
            BSTNode leftSubTree = node.left;
            node.left = null;
            return leftSubTree;
        }
    }
    /**
     * 查找传入节点树下value值最大的节点并放回该节点
     * 在二叉排序树中最大值的节点就是最右叶子节点
     * @param node
     * @return
     */
    public BSTNode max(BSTNode node){
        BSTNode max = node;
        while (max.right != null){
            max = max.right;
        }
        return max;
    }

    public void midOrder(){
        if (root != null){
            midOrder(root);
        }else {
            System.out.println("二叉顺序树为空,无法遍历");
        }
    }

    //中序遍历
    public void midOrder(BSTNode node){
        if (node.left != null){
            midOrder(node.left);
        }
        System.out.println(this);
        if (node.right != null){
            midOrder(node.right);
        }
    }
}

//二叉排序树节点
class BSTNode{
    int value;
    BSTNode left;
    BSTNode right;

    public BSTNode(int value){
        this.value = value;
    }

    @Override
    public String toString() {
        return "BSTNode{" +
                "value=" + value +
                '}';
    }
}

 

Guess you like

Origin blog.csdn.net/a159357445566/article/details/109062324