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
posted @ 2020-06-12 16:53  卡文迪雨  阅读(254)  评论(0编辑  收藏  举报