使用二分搜索树实现map

二分搜索树的相关内容

二分搜索树-------1_qq_15255121的专栏-CSDN博客

二分搜索树-------2 查询与遍历_qq_15255121的专栏-CSDN博客

二分搜索树-------3 删除元素_qq_15255121的专栏-CSDN博客

下面是具体的代码

package com.yuanxuzhen.map;

import com.yuanxuzhen.tree.YuanBST;

public class YuanBstMap <K extends Comparable<K>, V> implements Map<K, V>{
    private class Node{
        Node left;
        Node right;
        K key;
        V value;

        public Node(K key, V value) {
            this.key = key;
            this.value = value;
            this.left = null;
            this.right = null;
        }
    }

    private Node root;
    private int size;

    public YuanBstMap() {
        this.root = null;
        this.size = 0;
    }

    @Override
    public void add(K key, V value) {
        root = add(root, key, value);
    }



    private Node add(Node node, K key, V value){
        //null可以看做是二叉树
        if(node == null){
            ++size;
            return new Node(key, value);
        }
        if(key.compareTo(node.key) < 0){
            //如果插入的元素小于节点值,且左子树不为空,递归插入左子树
            node.left = add(node.left, key, value);
        }else if(key.compareTo(node.key) > 0){
            //如果插入的元素大于节点值,且右子树不为空,递归插入右子树
            node.right = add(node.right, key, value);
        }else{
            node.value = value;
        }

        return node;

    }

    @Override
    public V remove(K key) {
        Node node = getNote(root, key);
        if(node != null){
            root = remove(root, key);
            return node.value;
        }
        return null;
    }



    @Override
    public boolean contains(K key) {
        return getNote(root, key) != null;
    }

    @Override
    public V get(K key) {
        Node node = getNote(root, key);
        if(node != null){
            return node.value;
        }
        return null;
    }

    private Node  getNote(Node node, K key){
        if(node == null){
            return null;
        }

        if(key.compareTo(node.key) < 0){
            return  getNote(node.left, key);
        }else if(key.compareTo(node.key) > 0){
            return  getNote(node.right, key);
        }else {
            return node;
        }

    }

    @Override
    public void set(K key, V value) {
        Node node = getNote(root, key);
        if(node != null){
            node.value = value;
        }
    }

    @Override
    public int getSize() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }


    /**
     * 二分搜索树的特点,每个节点最多只有两个子节点,左节点 < 根节点 < 右节点
     * 所以最左侧的节点就是最小值
     * @return
     */
    public V minmum(){
        if(size == 0){
            throw new IllegalArgumentException("树为空");
        }
        return minmum(root).value;
    }

    private Node minmum(Node node){
        if(node.left == null){
            return node;
        }
        return minmum(node.left);
    }

    /**
     * 二分搜索树的特点,每个节点最多只有两个子节点,左节点 < 根节点 < 右节点
     * 所以最右侧的节点就是最大值
     * @return
     */
    public V maxMum(){
        if(size == 0){
            throw new IllegalArgumentException("树为空");
        }
        return minmum(root).value;
    }

    private Node maxMum(Node node){
        if(node.right == null){
            return node;
        }
        return maxMum(node.right);
    }


    /**
     * 删除最小值,最小值所在的节点,左子树为null,右子树可能不为null也可能是null
     * 如果右子树为null,那么直接删除当前节点即可,即把父节点的左子树置位null即可。
     * 如果右子树不为null,那么删除当前节点,同时把当前节点的右子树置为父节点的左子树
     * @return
     */
    public V removeMin(){
        V entry = minmum();
        root = removeMin(root);
        return entry;
    }

    private Node removeMin(Node node){
        if(node.left == null){
            //这里把null当做了特殊的节点,不管右节点是否为null,都要返回右节点,做为父节点的左子树
            Node rightNode = node.right;
            rightNode.right = null;
            size--;
            return rightNode;
        }
        //继续寻找最小的节点
        node.left = removeMin(node.left);
        return node;
    }

    /**
     * 删除最大值,最大值所在的节点,一直向右找,右子树为null,左子树可能不为null也可能是null
     * 如果左子树为null,那么直接删除当前节点即可,即把父节点的右子树置位null即可。
     * 如果左子树不为null,那么删除当前节点,同时把当前节点的左子树置为父节点的右子树
     * @return
     */
    public V removeMax(){
        V entry = maxMum();
        root = removeMax(root);
        return entry;
    }

    private Node removeMax(Node node){
        if(node.right == null){
            //这里把null当做了特殊的节点,不管左节点是否为null,都要返回左节点,做为父节点的右子树
            Node leftNode = node.left;
            leftNode.right = null;
            size--;
            return leftNode;
        }
        //继续寻找最大的节点
        node.right = removeMax(node.right);
        return node;
    }




    private Node remove(Node node, K key){
        if(key.compareTo(node.key) < 0){
            node.left = remove(node.left, key);
            return node;
        }else if(key.compareTo(node.key) > 0){
            node.right = remove(node.right, key);
            return node;
        }else{
            if(node.left == null){
                Node rightNote = node.right;
                node.right = null;
                return rightNote;
            }else if(node.right == null){
                Node leftNode = node.left;
                node.left = null;
                return leftNode;
            }else{
                /**
                 * 删除的节点左右子树都不为空,这里有两种处理方式,
                 * 用左子树的最大值或者右子树的最小值代替。都可以满足做子树<根节点<右子树
                 */
                Node replaceNode = null;
                //使用左子树的最大值
//                replaceNode = maxMum(node.left);
//                node.left = removeMax(node.left); //这里二叉树少了一个元素
//                size++; //少了的元素我们还要使用所以这里要加回来
//                //替换节点替换当前节点

                //使用右子树的最小值
                replaceNode = minmum(node.right);
                node.right = removeMin(node.right); //这里二叉树少了一个元素
                size++; //少了的元素我们还要使用所以这里要加回来



                //替换节点替换当前节点
                replaceNode.left = node.left;
                replaceNode.right = node.right;
                node.left = node.right = null; //删除了当前节点
                size--;

                return replaceNode;
            }


        }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值