TreeMap与TreeSet(初步了解)

TreeMap与TreeSet(初步了解)_第1张图片

日升时奋斗,日落时自省 

目录

一、Map和Set

1、搜索树的基本概念

 2、二叉搜索查找

3、二叉搜索树插入

4、二叉搜索树删除

 二、TreeMap

 三、TreeSet

一、Map和Set

Map/Set 及实际实现类 HashMap/TreeMap/HashSet/TreeSet 的使用,本次复习TreeMap和TreeSet

Map和set是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关:

1.直接遍历,时间复杂度为O(N),元素如果比较多效率会非常慢
2. 二分查找,时间复杂度为O(log_{2}n ),但搜索前必须要求序列是有序的
放入现实中都很难遇到巧合的情况,集合就更针对实现的复杂情况,动态查找集合便是更优的选择Map和Set就是动态查找容器

TreeMap是一个搜索树,但是不仅仅是一颗搜索树,因为单单的搜索树是不能实现很多情况为最优

搜索树相对于TreeMap其他底层代码更简单,初步入手

1、搜索树的基本概念

二叉搜索树也叫二叉排序树,基本性质:
左子树所有节点的值都小于根节点的值;

右子树所有节点的值都大于根节点的值;

它的左右子树都遵循前面的条件,分别也会构成二叉搜索树,这一整棵树才算是二叉搜索树

用一个数据举例:5  3  4  1  7  8  2  6  0  9

TreeMap与TreeSet(初步了解)_第2张图片

 2、二叉搜索查找

二叉搜索树的查找有点类似于二分法查找,每次找的数据都会与当前根的值进行比较,大于根节点的就向根的右边进行查找,小于根节点的就向左边进行查找

借上面的图

TreeMap与TreeSet(初步了解)_第3张图片

思路解析:

(1)一颗搜索树不为空情况下

(2)节点值==key,return true;

(3)节点值>key,向左子树找

(4)节点值

(5)key在二叉搜索树中不存在,return false

 图解:

(1)空树

TreeMap与TreeSet(初步了解)_第4张图片

 (2)非空书

TreeMap与TreeSet(初步了解)_第5张图片

static  class  NodeTree{
        public int val;
        public NodeTree left;
        public NodeTree right;

        public NodeTree(int val){
            this.val=val;
        }
    }
    public static NodeTree root=null;
public boolean search(int key){
        NodeTree cur=root;
        while(cur!=null){   //树不为空
            if(cur.val>key) {    //节点值>key,向左子树找
                cur=cur.left;
            }else if(cur.val

3、二叉搜索树插入

开始已经知道二叉树是什么了,插入其实就比较简单了

思路:

(1)树为空的情况,直接插入  (树为空)

(2)比根节点小,向左子树走 (树不为空)

(3)比根节点大,向右子树走

(4)如果找到一样的值了,就返回false

(5)直到走到空,就可以插入了

注:找到空了,怎么插入呢,这里就需要一个知道他的父节点,所以这里要记录一个父节点

(1)空树 

TreeMap与TreeSet(初步了解)_第6张图片

 (2)非空树TreeMap与TreeSet(初步了解)_第7张图片

代码解析:

public  boolean insert(int key){   //二叉搜索树进行插入
        if(root==null){
            root=new NodeTree(key);   //如果为空的话就只插入
            return true;
        }
        NodeTree cur=root;
        NodeTree parent=null;          //这里记录一下父节点,为了后面找到插入位置,进行连接
        while(cur!=null){               //树不为空,一直找
            if(cur.val>key){          //跟节点值小的,
                parent=cur;           //记录当前父节点
                cur=cur.left;          //找右子树
            }else if(cur.val parent.val){           //比父亲节点小,左边插入
            parent.right=node;
        }else{                         //比父亲节点大,右边插入
            parent.left=node;                
        }
        return true;
    }

4、二叉搜索树删除

删除的步骤就相对较多了

思路: 分析以下情况   (设置待删除节点为cur,当前父节点为parent)

(1)cur.left==null

(2)cur.right==null

(3)cur.left!=null&&cur.right!=null

以上三种情况,我们通过图解来详细解释

用替换法将待删除的值替换,并且保证整个二叉搜索树不会动摇

图解:

TreeMap与TreeSet(初步了解)_第8张图片

TreeMap与TreeSet(初步了解)_第9张图片

TreeMap与TreeSet(初步了解)_第10张图片

TreeMap与TreeSet(初步了解)_第11张图片

特殊情况:

 TreeMap与TreeSet(初步了解)_第12张图片

 代码解析:

代码是与图是相反的可以看着图来推当前代码

public void removeNode(NodeTree parent,NodeTree cur){
        if(cur.left==null){   //为了找到待删除的值
            if(cur==root){
                root=cur.right;
            }else if(cur==parent.left){
                parent.left=cur.right;
            }else if(cur==parent.right){
                parent.right=cur.right;
            }
        }else if(cur.right==null){
            if(cur==root){
                root=cur.left;
            }else if(cur==parent.left){
                parent.left=cur.left;
            }else  if(cur==parent.right){
                parent.right=cur.left;
            }
        }else{   //这里我们取一种就可以了
            NodeTree target=cur.right;
            NodeTree targetparent=cur;
            while(target.left!=null) {   //为了找替换值
                targetparent=target;
                target=target.left;
            }
            cur.val=target.val;
            if(target==targetparent.left){  //分两种情况
                targetparent.left=target.right;
            }else{
                targetparent.right=target.right;
            }
        }
    }

TreeMap与TreeSet(初步了解)_第13张图片

 二、TreeMap

里面是一个集合 ,TreeMap的底层代码是一个Map集合接口

Map底层结构 TreeMap
底层结构 红黑树
插入/删除/查找时间
复杂度
O(1)
是否有序 关于Key有序
线程安全 不安全
插入/删除/查找区别 需要进行元素比较
比较与覆写 key必须能够比较,否则会抛出
ClassCastException异常
应用场景 需要Key有序场景下

TreeMap与TreeSet(初步了解)_第14张图片

TreeMap与TreeSet(初步了解)_第15张图片

 泛型有两个第一个传入key,第二个传入value

TreeMap与TreeSet(初步了解)_第16张图片

这里的key是可以比较的key值,传key时调用了比较器,如果不是可以比较的,就会报错

TreeMap与TreeSet(初步了解)_第17张图片

 put方法就是将我们需要的key,value值放入存储起来

getOrDefault方法是key是否找到,如果没有就返回默认值

TreeMap与TreeSet(初步了解)_第18张图片

除了上面的方法,还有以下比较基本的方法使用,可以尝试 

方法 解释
V get(Object key) 返回 key 对应的 value
V getOrDefault(Object key, V defaultValue) 返回 key 对应的 value,key 不存在,返回默认值
V put(K key, V value) 设置 key 对应的 value
V remove(Object key) 删除 key 对应的映射关系
Set keySet() 返回所有 key 的不重复集合
Collection values() 返回所有 value 的可重复集合
Set> entrySet() 返回所有的 key-value 映射关系
boolean containsKey(Object key) 判断是否包含 key
boolean containsValue(Object value) 判断是否包含 value

TreeMap与TreeSet(初步了解)_第19张图片TreeMap与TreeSet(初步了解)_第20张图片

 前面的图TreeMap用Set棘手后打印

那Map的打印应怎么处理呢

这里肯定不能用foreach,迭代打印因为都没有继承关系

代码解释:

public static void main(String[] args) {
        Map map=new TreeMap<>();
        map.put("hello",2);
        map.put("abc",1);
        Set> entries=map.entrySet();
        for (Map.Entry set:entries) {
            System.out.println(set.getKey()+" "+set.getValue());
        }
    }

图解一下:

TreeMap与TreeSet(初步了解)_第21张图片

 三、TreeSet

TreeSet的底层是TreeMap,去掉重复的元素,key的重复不会再搜索树中出现

TreeSet继承了Set,Set又继承了Collection

注:将Map与Set联系起来Set> entries=map.entrySet();

才能使用Iterable中迭代打印,foreach打印等方法,Map一系中是独立出来并没有实现在下面的关系图中,TreeSet弥补了当前的缺陷。

TreeMap与TreeSet(初步了解)_第22张图片

 TreeSet的底层是TreeMap,直接将TreeMap与上面的关系图联系起来,TreeSet也同样有TreeMap的限制,泛型传值中是需要经过比较。(用于Map相同的方法)

TreeMap与TreeSet(初步了解)_第23张图片

 Set> entries=map.entrySet();

解释:

TreeMap与TreeSet(初步了解)_第24张图片

你可能感兴趣的:(Set和Map,数据结构,java)