zoukankan      html  css  js  c++  java
  • 08-映射 Map

    学习资源:慕课网liyubobobo老师的《玩儿转数据结构》


    1、映射 map简介

    • 存储(键,值)数据对的数据结构(Key, Value)

    • 键与值一一对应

    • 键不能重复

    • 重复添加同一个key,新的value会覆盖原先的value

    • 可以根据键(Key) ,寻找值(Value)

    • 非常容易使用链表或者二分搜索树实现

      // 链表的节点
      class Node {
          K key;
          V value
          Node next;
      }
      
      // 二分搜索树的节点
      class Node {
          K key;
          V value
          Node Left;
          Node right ;
      }
      

    2、map的接口

    public interface Map<K, V> {
    
        void add(K key, V value);
        V remove(K key);
        boolean ifContains(K key);
        V get(K key);
        void set(K key, V newValue);
        int getSize();
        boolean isEmpty();
    }
    

    3、映射的实现

    3.1、基于二分搜索树

    public class BSTMap<K extends Comparable<K>, V> implements Map<K, V> {
    
        private class Node {
            
            public K key;
            public V value;
            public Node left;
            public Node right ;
    
            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 BSTMap() {
            
            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){
    
            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;
        }
        //返回以node为根节点的二分搜索树中,key所在的节点
        private Node getNode(Node node, K key){
    
            if(node == null){
                return null;
            }
            if(key.compareTo(node.key) == 0){
                return node;
            }else if (key.compareTo(node.key) < 0){
                return getNode(node.left, key);
            }else {
                return getNode(node.right, key);
            }
        }
    
        @Override
        public V remove(K key) {
    
            Node node = getNode(root, key);
            if(node == null){
                return null;
            }
            root = remove(root, key);
            return node.value;
        }
        //删除掉以node为根的二分搜索树中键为key的节点,递归算法
        //返回删除节点后新的二分搜索树的根
        private Node remove(Node node, K key){
    
            if(node == null){
                return null;
            }
            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 rightNode = node.right;
                    node.right = null;
                    size--;
                    return rightNode;
                }
                if(node.right == null){
                    Node leftNode = node.left;
                    node.left = null;
                    size--;
                    return leftNode;
                }
    
                Node successor = minimum(node.right);
                successor.right = removeMin(node.right);
                successor.left = node.left;
                node.left = node.right = null;
    
                return successor;
            }
        }
        private Node minimum(Node node){
    
            if(node.left == null){
                return node;
            }
            return minimum(node.left);
        }
        private Node removeMin(Node node) {
    
            if(node.left == null){
                Node rightNode = node.right;
                node.right = null;
                size--;
                return rightNode;
            }
    
            node.left = removeMin(node.left);
            return node;
        }
    
        @Override
        public boolean ifContains(K key) {
            return getNode(root, key) != null;
        }
    
        @Override
        public V get(K key) {
            return getNode(root, key).value;
        }
    
        @Override
        public void set(K key, V newValue) {
    
            Node node = getNode(root, key);
            if(node == null){
                throw new IllegalArgumentException(key + "不存在");
            }
            node.value = newValue;
        }
    
        @Override
        public int getSize() {
            return size;
        }
    
        @Override
        public boolean isEmpty() {
            return size ==  0;
        }
    }
    

    3.2、基于链表

    package map;
    
    import linkedList.LinkedList;
    
    public class LinkedListMap<K, V> implements Map<K, V> {
    
        private class Node{
    
            public K key;
            public V value;
            public Node next;
    
            public Node(K key, V value, Node next) {
                this.key = key;
                this.value = value;
                this.next = next;
            }
    
            public Node(K key) {
                this(key, null, null);
            }
    
            public Node(){
                this(null, null, null);
            }
    
            @Override
            public String toString() {
                return key.toString() + " : " + value.toString();
            }
        }
    
        private int size;
        private Node dummyHead;
    
        public LinkedListMap() {
            dummyHead = new Node();
            size = 0;
        }
    
        private Node getNode(K key){
    
            Node cur = dummyHead.next;
            while(cur != null){
                if(cur.key.equals(key)){
                    return cur;
                }
                cur = cur.next;
            }
            return null;
        }
    
        @Override
        public void add(K key, V value) {
    
            Node node = getNode(key);
            if(node == null){
                dummyHead.next = new Node(key, value, dummyHead.next);
                size++;
            }
            else {
                node.value = value;
            }
        }
    
        @Override
        public V remove(K key) {
    
            Node prev = dummyHead;
            while (prev.next != null){
                if(prev.next.key.equals(key)){
                    break;
                }
                prev = prev.next;
            }
    
            if(prev.next != null){
                Node delNode = prev.next;
                prev.next = delNode.next;
                delNode.next = null;
                size--;
                return delNode.value;
            }
    
            return null;
        }
    
        @Override
        public boolean ifContains(K key) {
            return getNode(key) != null;
        }
    
        @Override
        public V get(K key) {
    
            Node node = getNode(key);
            return node == null ? null : node.value;
        }
    
        @Override
        public void set(K key, V newValue) {
    
            Node node = getNode(key);
            if(node == null){
                throw new IllegalArgumentException("map 中没有这个key");
            }
            else {
                node.value = newValue;
            }
        }
    
        @Override
        public int getSize() {
            return size;
        }
    
        @Override
        public boolean isEmpty() { 
            return size == 0;
        }
    }
    

    4、测试

    统计文本的词汇量,测试显示BSTMap速度远快于LinkedListMap

    public void test_2{
        
        ArrayList<String> words = new ArrayList<>();
        if(FileOperation.readFile("pride-and-prejudice.txt", words)){
        System.out.println("单词数:" +  words.size());
        LinkedListMap<String, Integer> linkedListMap = new LinkedListMap<>();
        for(String word : words){
            if(!linkedListMap.contains(word)){
                linkedListMap.add(word, 1);
            }else {
                linkedListMap.set(word, linkedListMap.get(word)+1);
            }
        }
        System.out.println("词汇量"+linkedListMap.getSize());
    }
    
    
    public void test_2{
        
        ArrayList<String> words = new ArrayList<>();
        if(FileOperation.readFile("pride-and-prejudice.txt", words)){
            System.out.println("单词数:" +  words.size());
            BSTMap<String, Integer> bstMap = new BSTMap<>();
            for(String word : words){
                if(!bstMap.contains(word)){
                    bstMap.add(word, 1);
                }else {
                    bstMap.set(word, bstMap.get(word)+1);
                }
            }
            System.out.println("词汇量"+bstMap.getSize());
        }
    }
    

    5、Java中的Map

    TreeMap

    底层基于二分搜索树

    public class TreeMap<K,V>
        extends AbstractMap<K,V>
        implements NavigableMap<K,V>, Cloneable, java.io.Serializable
    {
        
    }
    

    API接口

    image-20200612164459220 image-20200612164534633

    HashMap

    底层基于哈希表

    public class HashMap<K,V> extends AbstractMap<K,V>
        implements Map<K,V>, Cloneable, Serializable 
    {
        
    }
    

    API接口

    image-20200612164812396
  • 相关阅读:
    Git 数据是怎么存储的
    技术管理规划-路径跟资源
    技术管理规划-如何规划团队的架构
    技术管理规划-如何设定团队的目标
    技术管理规划-设定团队的职能
    springboot实践1
    spring的事件机制实战
    Apollo的基本概念和集成实战
    spring的事件
    ELK的简单安装使用
  • 原文地址:https://www.cnblogs.com/sout-ch233/p/13100475.html
Copyright © 2011-2022 走看看