特点

  • 左子树的每个结点的值都比根节点小,右子树的每个结点的值都比根节点大
  • 中序遍历为一个有序序列

二叉搜索树.png

时间复杂度

  • 查找 O(logn)
  • 插入 O(1)
  • 删除 O(logn) 寻找前继结点或者后继结点 替换删除的结点

前继结点:第一个比根节点小的数
后继结点:第一个比根节点大的数

代码实现

public class TreeNode<E> {
    private TreeNode<E> leftNode;
    private Integer key;
    private E data;
    private TreeNode<E> rightNode;
    private TreeNode<E> parentNode;

    public TreeNode(Integer key, E data) {
        this.key = key;
        this.data = data;
    }

    public TreeNode(TreeNode<E> leftNode, E data, TreeNode<E> rightNode) {
        this.leftNode = leftNode;
        this.data = data;
        this.rightNode = rightNode;
    }

    public TreeNode<E> getLeftNode() {
        return leftNode;
    }

    public void setLeftNode(TreeNode<E> leftNode) {
        this.leftNode = leftNode;
    }

    public E getData() {
        return data;
    }

    public void setData(E data) {
        this.data = data;
    }

    public TreeNode<E> getRightNode() {
        return rightNode;
    }

    public void setRightNode(TreeNode<E> rightNode) {
        this.rightNode = rightNode;
    }

    public Integer getKey() {
        return key;
    }

    public void setKey(Integer key) {
        this.key = key;
    }

    public void setParentNode(TreeNode<E> parentNode) {
        this.parentNode = parentNode;
    }

    public TreeNode<E> getParentNode() {
        return parentNode;
    }
}

public class BinarySelectTree<E> {
    private int size;
    private TreeNode<E> rootNode;

    public void insert(Integer key, E data) {
        if (rootNode == null) {
            rootNode = new TreeNode<>(key, data);
            size++;
            return;
        }
        insert(rootNode, key, data);
        size++;
    }

    private void insert(TreeNode<E> treeNode, Integer key, E data) {
        Integer rootKey = treeNode.getKey();
        TreeNode<E> leafNode = new TreeNode<>(key, data);
        if (rootKey >= key) {
            if (treeNode.getLeftNode() != null) {
                insert(treeNode.getLeftNode(), key, data);
            } else {
                treeNode.setLeftNode(leafNode);
                leafNode.setParentNode(treeNode);
            }
        } else {
            if (treeNode.getRightNode() != null) {
                insert(treeNode.getRightNode(), key, data);
            } else {
                treeNode.setRightNode(leafNode);
                leafNode.setParentNode(treeNode);
            }
        }
    }

    public E find(Integer key) {
        if (rootNode != null) {
            TreeNode<E> eTreeNode = find(rootNode, key);
            if (eTreeNode != null)
                return eTreeNode.getData();
        }
        return null;
    }

    private TreeNode<E> find(TreeNode<E> treeNode, Integer key) {
        Integer rootKey = treeNode.getKey();
        if (rootKey > key) {
            if (treeNode.getLeftNode() != null) {
                return find(treeNode.getLeftNode(), key);
            }
        } else if (rootKey < key) {
            if (treeNode.getRightNode() != null) {
                return find(treeNode.getRightNode(), key);
            }
        } else
            return treeNode;
        return null;
    }


    public int size() {
        return size;
    }

    public void print(TreeNode<E> treeNode) {
        System.out.print(treeNode.getData());
    }

    public void pre() {
        if (rootNode != null)
            pre(rootNode);
    }

    //前序遍历 根 左 右
    public void pre(TreeNode<E> treeNode) {
        print(treeNode);
        if (treeNode.getLeftNode() != null)
            pre(treeNode.getLeftNode());
        if (treeNode.getRightNode() != null)
            pre(treeNode.getRightNode());
    }

    public void mid() {
        if (rootNode != null)
            mid(rootNode);
    }


    //中序遍历 左 根 右
    private void mid(TreeNode<E> treeNode) {
        if (treeNode.getLeftNode() != null) {
            mid(treeNode.getLeftNode());
        }
        print(treeNode);
        if (treeNode.getRightNode() != null)
            mid(treeNode.getRightNode());
    }

    public void post() {
        if (rootNode != null)
            post(rootNode);
    }

    //后序遍历 左 右 根
    public void post(TreeNode<E> treeNode) {
        if (treeNode.getLeftNode() != null) {
            post(treeNode.getLeftNode());
        }
        if (treeNode.getRightNode() != null) {
            post(treeNode.getRightNode());
        }
        print(treeNode);
    }

    //层序遍历
    public void level(TreeNode<E> treeNode) {
        MyQueue<TreeNode<E>> queue = new MyQueue<>(20);
        levelRecursion(queue, treeNode);
    }

    private void levelRecursion(MyQueue<TreeNode<E>> queue, TreeNode<E> treeNode) {
        print(treeNode);
        if (treeNode.getLeftNode() != null) {
            queue.push(treeNode.getLeftNode());
        }
        if (treeNode.getRightNode() != null) {
            queue.push(treeNode.getRightNode());
        }
        while (!queue.isEmpty()) {
            levelRecursion(queue, queue.pop());
        }
    }

    public void remove(Integer key) {
        //1.找到该key
        //2.找到该key的后继结点
        //3.替换
        TreeNode<E> node = find(rootNode, key);
        if (node == null) return;

        TreeNode<E> postNode ;
        if (node.getLeftNode() != null && node.getRightNode() != null) {
            //此时需寻找后继结点 右子树的最小结点
            postNode = findPostNode(node.getRightNode());
            TreeNode<E> postParentNode = postNode.getParentNode();
            postParentNode.setLeftNode(postNode.getRightNode());
            postNode.setLeftNode(node.getLeftNode());
            postNode.setRightNode(node.getRightNode());
        }else {
            //至少有一个为空
            postNode = node.getLeftNode() != null ? node.getLeftNode() : node.getRightNode();
        }
        //判断删除的是左结点还是右结点
        TreeNode<E> parentNode = node.getParentNode();
        if(parentNode==null){
            //删除的是根结点
            rootNode = postNode;
            rootNode.setParentNode(null);
            return;
        }
        TreeNode<E> leftNode = parentNode.getLeftNode();
        if (leftNode != null && leftNode == node) {
            parentNode.setLeftNode(postNode);
        } else {
            parentNode.setRightNode(postNode);
        }
        postNode.setParentNode(parentNode);
    }

    public TreeNode<E> findPostNode(TreeNode<E> node) {
        if (node.getLeftNode() != null) {
            findPostNode(node.getLeftNode());
        }
        return node;
    }
}