二叉排序树(BST)

参考文章

定义

一棵空树,或者是具有下列性质的二叉树:

1 若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2) 若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3) 左、右子树也分别为二叉排序树;
4) 没有键值相等的结点。

代码实现如下,参考文章的图解和思路都超赞

/**
 * 二叉排序树节点
 */
public class BSTreeNode {

    /**
     * 树的标识
     */
    private int key;

    /**
     * 左子节点
     */
    private BSTreeNode leftNode;
    /**
     * 右子节点
     */
    private BSTreeNode rightNode;

    public BSTreeNode() {
    }

    public BSTreeNode(int key) {
        this.key = key;
    }

    public int getKey() {
        return key;
    }

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

    public BSTreeNode getLeftNode() {
        return leftNode;
    }

    public void setLeftNode(BSTreeNode leftNode) {
        this.leftNode = leftNode;
    }

    public BSTreeNode getRightNode() {
        return rightNode;
    }

    public void setRightNode(BSTreeNode rightNode) {
        this.rightNode = rightNode;
    }

    @Override
    public String toString() {
        return "BSTreeNode{" +
                "key=" + key +
                '}';
    }

    /**
     * 添加子节点
     *
     * @param node
     */
    public void add(BSTreeNode node) {
        if (node == null) {
            return;
        }
        if (this.key == node.key) {
            System.out.println("该节点已存在");
            return;
        }
        //放在该节点的左边
        if (node.key < this.key) {
            //如果没有左子节点,那么就放左子节点
            if (this.leftNode == null) {
                this.leftNode = node;
            } else {
                //继续递归
                this.leftNode.add(node);
            }
        } else {
            //放在该节点的右边
            //如果没有右子节点,那么就放右子节点
            if (this.rightNode == null) {
                this.rightNode = node;
            } else {
                //继续递归
                this.rightNode.add(node);
            }
        }

    }
    
}



/**
 * 二叉排序树(二叉搜索树 BinarySearchTree)
 * 

* 实现功能 * 1.添加 * 2.查找 * 3.删除 */ public class BSTree { /** * 根节点 */ private BSTreeNode root; /** * 添加节点 * * @param node */ public void add(BSTreeNode node) { if (root == null) { root = node; return; } //添加 root.add(node); } /** * 删除节点 * * @param key */ public void delete(int key) { BSTreeNode parent = searchParent(key); if (parent == null) { System.out.println("parent未找到"); return; } //找到等待删除的节点 BSTreeNode target; //跟parent的子节点进行比对 if (parent.getLeftNode() != null && parent.getLeftNode().getKey() == key) { target = parent.getLeftNode(); } else { target = parent.getRightNode(); } System.out.println("key=" + key + "parent=" + parent + "target=" + target); //那么就有三种情况 //1.待删除节点是叶子节点,那么就直接删 //2.待删除节点下有单个子节点,那么就节点上移 //3.待删除节点下存在两个子节点,那么就把右子节点下最小的值上移 int num = getChildNum(target); //分别出来三种情况 if (num == 0) { //进入情况1 //如果是左节点就删除左节点,是右节点就删除右节点 if (target == parent.getLeftNode()) { parent.setLeftNode(null); } else { parent.setRightNode(null); } } else if (num == 1) { //情况2 //如果是左节点就删除左节点的子节点上提,是右节点就上提右子节点的子节点 BSTreeNode child = getSingleChild(target); if (target == parent.getLeftNode()) { parent.setLeftNode(child); } else { parent.setRightNode(child); } } else { //情况3 ,待删除的子节有两个子节点 //找出右子节点下最小的那个节点,替换到待删除节点 BSTreeNode minChild = getMinChild(target); //删除该节点 delete(minChild.getKey()); //然后替换,完成 target.setKey(minChild.getKey()); } } /** * 遍历查询子数下最小的节点 * * @param target * @return */ private BSTreeNode getMinChild(BSTreeNode target) { BSTreeNode temp = target.getLeftNode(); while (temp.getLeftNode() != null) { temp = temp.getLeftNode(); } return temp; } /** * 获取唯一的孩子节点 * * @param target * @return */ private BSTreeNode getSingleChild(BSTreeNode target) { //左子节点存在就返回,否则返回右子节点 return target.getLeftNode() != null ? target.getLeftNode() : target.getRightNode(); } /** * 获取该节点左右子节点的个数 * * @param node * @return */ private int getChildNum(BSTreeNode node) { int num = 0; //存在左子节点 if (node.getLeftNode() != null) { num++; } //存在右子节点 if (node.getRightNode() != null) { num++; } return num; } /** * 搜索 * * @param key * @return */ public BSTreeNode search(int key) { if (null == root) { return null; } BSTreeNode node = root; while (node != null) { int match = node.getKey(); if (key == match) { return node; } if (key < match) { node = node.getLeftNode(); } else { node = node.getRightNode(); } } return null; } /** * 搜索待删除节点的父节点 * * @param key * @return */ public BSTreeNode searchParent(int key) { if (null == root) { return null; } BSTreeNode temp = root; while (temp != null) { //跟它的子节点进行匹配,匹配任意一个都好使 if ((temp.getLeftNode() != null && temp.getLeftNode().getKey() == key) || (temp.getRightNode() != null && temp.getRightNode().getKey() == key)) { return temp; } //不匹配的话,继续查找 int match = temp.getKey(); if (key < match) { temp = temp.getLeftNode(); } else { temp = temp.getRightNode(); } } return null; } /** * 中序遍历 */ public void midTraverse() { if (root == null) { return; } midTraverse(root); } /** * 中序遍历 * * @param node */ private void midTraverse(BSTreeNode node) { if (node.getLeftNode() != null) { midTraverse(node.getLeftNode()); } System.out.println(node); if (node.getRightNode() != null) { midTraverse(node.getRightNode()); } } } /** * 测试代码 * @param args */ public static void main(String[] args) { int[] array = new int[]{50, 30, 80, 20, 35, 34, 32, 40, 70, 75, 100}; BSTree tree = new BSTree(); for (int i = 0; i < array.length; i++) { int key = array[i]; BSTreeNode node = new BSTreeNode(key); tree.add(node); } System.out.println("中序遍历"); tree.midTraverse(); System.out.println("搜索20=" + tree.search(20)); System.out.println("搜索200=" + tree.search(200)); //删除节点 tree.delete(30); System.out.println("中序遍历"); tree.midTraverse(); }

你可能感兴趣的:(数据结构与算法)