天天看点

Java 树 二叉查找树(又二叉排序树)

知识点:

​​树的遍历​​​​​​

​​树的分类​​

树代码的实现,主要是用到了,递归

二叉树代码实现

增加,删除,查找

功能实现

删除节点操作稍微麻烦点

删除目标节点target有3种情况

  1. target为叶子节点
  2. target只有一个子节点
  3. target有两个子节点

情况3最麻烦

首先找到替换的元素

target的左子树中最大的元素or其右子树中最小的元素

直接把键值对替换,然后删除叶子节点即可

可以挑,

其中会有两个方法,

  • 第一个是在整个树中删除key对应的值
  • 第二个是在对应的子树x中删除键值对key

第一步找到要删除的key键值对,

一个整体的架构

Java 树 二叉查找树(又二叉排序树)

代码问题,只判断 了当前节点的下一个左节点是否为空,然后就断开了,

没有判断最后一个节点的右节点是否为空

Java 树 二叉查找树(又二叉排序树)
package cn.itcast.algorithm.tree;

//二叉树代码
public class BinaryTree<Key extends Comparable<Key>, Value> {
    //记录根结点
    private Node root;
    //记录树中元素的个数
    private int N;

    //获取树中元素的个数
    public int size() {
        return N;
    }

    //向树中添加元素key-value
    public void put(Key key, Value value) {
        root = put(root, key, value);
    }

    //向指定的树x中添加key-value,并返回添加元素后新的树
    //私有方法,只能通过上面的方法来调用私有方法
    private Node put(Node x, Key key, Value value) {
        if (x == null) {
            //个数+1
            N++;
            return new Node(key, value, null, null);
        }
        int cmp = key.compareTo(x.key);
        if (cmp > 0) {
            //新结点的key大于当前结点的key,继续找当前结点的右子结点
            x.right = put(x.right, key, value);
        } else if (cmp < 0) {
            //新结点的key小于当前结点的key,继续找当前结点的左子结点
            x.left = put(x.left, key, value);
        } else {
            //新结点的key等于当前结点的key,把当前结点的value进行替换
            x.value = value;
        }
        return x;
    }

    //查询树中指定key对应的value
    public Value get(Key key) {
        return get(root, key);
    }

//从指定的树x中,查找key对应的值
public Value get(Node x, Key key) {
    if (x == null) {
        return null;
    }
    int cmp = key.compareTo(x.key);
    if (cmp > 0) {
        //如果要查询的key大于当前结点的key,则继续找当前结点的右子结点;
        return get(x.right, key);
    } else if (cmp < 0) {
        //如果要查询的key小于当前结点的key,则继续找当前结点的左子结点;
        return get(x.left, key);
    } else {
        //如果要查询的key等于当前结点的key,则树中返回当前结点的value。
        return x.value;
    }
}

    //删除树中key对应的value
    public void delete(Key key) {
        root = delete(root, key);
    }

    //删除指定树x中的key对应的value,并返回删除后的新树
    public Node delete(Node x, Key key) {
        if (x == null) {
            return null;
        }

        int cmp = key.compareTo(x.key);
        if (cmp > 0) {
            //新结点的key大于当前结点的key,继续找当前结点的右子结点
            x.right = delete(x.right, key);
        } else if (cmp < 0) {
            //新结点的key小于当前结点的key,继续找当前结点的左子结点
            x.left = delete(x.left, key);
        } else {
            //新结点的key等于当前结点的key,当前x就是要删除的结点
            //1.如果当前结点的右子树不存在,则直接返回当前结点的左子结点
            if (x.right == null) {
                return x.left;
            }
            //2.如果当前结点的左子树不存在,则直接返回当前结点的右子结点
            if (x.left == null) {
                return x.right;
            }
            //3.当前结点的左右子树都存在
            //3.1找到右子树中最小的结点
            Node minNode = x.right;
            while (minNode.left != null) {
                minNode = minNode.left;
            }
            //3.2删除右子树中最小的结点
            Node n = x.right;
            while (n.left != null) {
                if (n.left.left == null) {
                    n.left = null;
                } else {
                    n = n.left;
                }
            }

            //3.3让被删除结点的左子树称为最小结点minNode的左子树,让被删除结点的右子树称为最小结点minNode的右子树
            minNode.left = x.left;
            minNode.right = x.right;
            //3.4让被删除结点的父节点指向最小结点minNode
            x = minNode;
            //个数-1
            N--;
        }
        return x;
    }

    private class Node {
        //存储键
        public Key key;
        //存储值
        private Value value;
        //记录左子结点
        public Node left;
        //记录右子结点
        public Node right;

        public Node(Key key, Value value, Node left, Node right) {
            this.key = key;
            this.value = value;
            this.left = left;
            this.right = right;
        }
    }
}      

​​https://www.bilibili.com/video/BV1iJ411E7xW?p=83​​

继续阅读