TreeMap及 TreeSet

提及TreeMap及 TreeSet,我们首先来了解他们底层是用什么来实现的,通过观看Java的源码,我们知道他们的底层都是由二叉搜索树实现的,那我们先来了解一下二叉搜索树
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树 :
        若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
        若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
        它的左右子树也分别为二叉搜索树
看完二叉搜索时的性质,我们来自己创建一个二叉搜索数
public class BinarySearchTree {
    static class TreeNode{
        public int val;
        public TreeNode left;
        public TreeNode right;

        public  TreeNode(int val){
            this.val = val;
        }
    }
    public TreeNode root = null;
}

首先实现查找(val)

 /**
     * 查找二叉搜索树中指定的val值
     * @param val
     * @return
     */
    public TreeNode find(int val){
        TreeNode cur = root;
        while (cur != null){
            if(cur.val < val){
                cur = cur.right;
            }else if(cur.val == val){
                return cur;
            }else {
                cur = cur.left;
            }
        }
        return null;
    }

思路:利用二叉搜索树性质,右侧树比左侧大,直接砍掉一半,然后用==确认val值。

接下来就是二叉搜索树的插入代码实现

 /**
     * 插入(val)
     * @param val
     */
    public void insert(int val){
        if(root == null){
            root = new TreeNode(val);
            return;
        }
        TreeNode cur = root;
        TreeNode parent = null;
        while (cur != null){
            if(cur.val < val){
                parent = cur;
                cur = cur.right;
            }else if(cur.val == val){
                return;
            }else {
                parent = cur;
                cur = cur.left;
            }
        }
        TreeNode node = new TreeNode(val);
        if(parent.val < val){
            parent.right = node;
        }else {
            parent.left = node;
        }
    }

    public void inorder(TreeNode root) {
        if(root == null) {
            return;
        }
        inorder(root.left);
        System.out.print(root.val+" ");
        inorder(root.right);
    }

思路:

 

 

删除操作(val)

 /**
     * 删除关键字(val)
     * @param val
     */
    public void remove(int val){
        TreeNode cur = root;
        TreeNode parent = null;

        while (cur != null){
            if (cur.val < val){
                parent = cur;
                cur = cur.right;
            }else if(cur.val == val){
                removeNode(parent,cur);
                return;
            }else {
                parent = cur;
                cur = cur.left;
            }
        }
    }
    private void removeNode(TreeNode parent,TreeNode cur){
        if(cur.left == null){
            if(cur == root){
                root = cur.right;
            }else if(parent.left == cur){
                parent.left = cur.right;
            }else {
                parent.right = cur.right;
            }
        }else if(cur.right == null){
            if(cur == root){
                root = cur.left;
            }else if(parent.left == cur){
                parent.left = cur.left;
            }else {
                parent.right = cur.left;
            }
        }else {
            TreeNode targetP = cur;
            TreeNode target = cur.right;
            while (target.left != null){
                targetP = target;
                target = target.left;
            }
            cur.val = target.val;
            if (targetP.left == target){
                targetP.left = target.right;
            }else {
                targetP.right = target.right;
            }
        }
    }

思路:

 

Map set 是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关
2.2 模型
一般把搜索的数据称为关键字( Key ),和关键字对应的称为值(
Value ),将其称之为 Key-value 的键值对,所以
模型会有两种:
1. key 模型 ,比如:
有一个英文词典,快速查找一个单词是否在词典中
快速查找某个名字在不在通讯录中
2. Key-Value 模型 ,比如:
统计文件中每个单词出现的次数,统计结果是每个单词都有与其对应的次数: < 单词,单词出现的次数 >
梁山好汉的江湖绰号:每个好汉都有自己的江湖绰号
Map 中存储的就是 key-value 的键值对, Set 中只存储了 Key

 

3.1 关于Map的说明

Map 是一个接口类,该类没有继承自 Collection ,该类中存储的是 <K,V> 结构的键值对,并且 K 一定是唯一的,不
能重复

 3.3 Map 的常用方法说明

注意:
1. Map 是一个接口,不能直接实例化对象 ,如果 要实例化对象只能实例化其实现类 TreeMap 或者 HashMap
2. Map 中存放键值对的 Key 是唯一的, value 是可以重复的
3. TreeMap 中插入键值对时, key 不能为空,否则就会抛 NullPointerException 异常 value 可以为空。但是HashMap key value 都可以为空。
4. Map 中的 Key 可以全部分离出来,存储到 Set 来进行访问 ( 因为 Key 不能重复 )
5. Map 中的 value 可以全部分离出来,存储在 Collection 的任何一个子集合中 (value 可能有重复 )
6. Map 中键值对的 Key 不能直接修改, value 可以修改,如果要修改 key ,只能先将该 key 删除掉,然后再来进行 重新插入。
代码实现
public static void main(String[] args) {
        Map<String,Integer> treeMap = new TreeMap<>();
        treeMap.put("zeq",22);
        treeMap.put("zjr",21);
        treeMap.put("zbb",0);
        System.out.println(treeMap.get("zeq"));
        //treeMap.put("zjr",28);
        System.out.println(treeMap);
        Set<String> keySet = treeMap.keySet();
        System.out.println(keySet);
        Set<Map.Entry<String,Integer>> Set = treeMap.entrySet();
        for (Map.Entry<String,Integer> entry:Set) {
            System.out.println("key:"+entry.getKey()+" value:"+entry.getValue());
        }
    }

运行结果

 

4. Set 的说明
Set Map 主要的不同有两点: Set 是继承自 Collection 的接口类, Set 中只存储了 Key

4.1 常见方法说明

 代码演示

 public static void main(String[] args) {
        Set<String> set = new TreeSet<>();
        set.add("i");
        set.add("love");
        set.add("you");
        System.out.println(set);
        System.out.println(set.contains("love"));
    }
运行结果:
注意:
1. Set 是继承自 Collection 的一个接口类
2. Set 中只存储了 key ,并且要求 key 一定要唯一
3. TreeSet 的底层是使用 Map 来实现的,其使用 key Object 的一个默认对象作为键值对插入到 Map 中的
4. Set最大的功能就是对集合中的元素进行去重
5. 实现 Set 接口的常用类有 TreeSet HashSet ,还有一个 LinkedHashSet LinkedHashSet 是在 HashSet 的基础
上维护了一个双向链表来记录元素的插入次序。
6. Set 中的 Key 不能修改,如果要修改,先将原来的删除掉,然后再重新插入
7. TreeSet 中不能插入 null key HashSet 可以。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值