(八) 映射(Map)

映射Map

  • Map是存储(键, 值) 数据对的数据结构
  • 根据键Key寻找值

基于链表的Map

Map接口

package pers.jssd.map;

/**
 * @author jssdjing@gmail.com
 * @create 2019/8/8 10:10
 */
public interface Map<K, V> {

    /**
     * 是否为空
     * @return true则map为空, false则不为空
     */
    boolean isEmpty();

    /**
     * map中存储数据的个数
     * @return 返回map中存储数据的个数
     */
    int getSize();

    /**
     * 添加元素
     * @param key 元素的key
     * @param value 元素的value
     */
    void add(K key, V value);

    /**
     * 根据key删除value并返回
     * @param key 需要删除元素的key
     * @return 返回删除的value, 如果为空, 则返回null
     */
    V remove(K key);

    /**
     * 设置键为key的元素为value
     * @param key 设置元素的key
     * @param value 需要设置的新value
     */
    void set(K key, V value);

    /**
     * 取得键为key的元素
     * @param key 要取得的元素的key
     * @return V value 返回键为key的元素
     */
    V get(K key);
}

链表实现Map代码

package pers.jssd.map;

/**
 * @author jssdjing@gmail.com
 * @create 2019/8/8 10:10
 */
public class LinkedListMap<K, V> implements Map<K, V> {

    /**
     * map的Node内部类
     */
    private class Node {
        K key;
        V value;
        Node next;

        public Node() {
            this.key = null;
            this.value = null;
            this.next = null;
        }

        public Node(K key, V value, Node next) {
            this.key = key;
            this.value = value;
            this.next = next;
        }
    }

    private Node dummyHead;
    private int size;

    public LinkedListMap() {
        dummyHead = new Node();
        size = 0;
    }

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

    /**
     * 通过key取得Node
     *
     * @param key 要取得Node的key
     * @return 返回取得的Node, 如果没有, 则返回null
     */
    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 int getSize() {
        return size;
    }

    @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 pre = dummyHead;
        while (pre.next != null) {
            if (pre.next.key.equals(key)) {
                Node delNode = pre.next;
                pre.next = delNode.next;
                delNode.next = null;
                size --;
                return delNode.value;
            }
            pre = pre.next;
        }
        return null;
    }

    @Override
    public void set(K key, V value) {
        Node cur = getNode(key);
        if (cur != null) {
            cur.value = value;
        } else {
            throw new IllegalArgumentException("No this key");
        }
    }

    @Override
    public V get(K key) {
        Node node = getNode(key);
        return null == node ? null : node.value;
    }
}

二分搜索树实现MAP代码

package pers.jssd.map;

/**
 * @author jssdjing@gmail.com
 */
public class BSTMap<K extends Comparable<K>, V> implements Map<K, V> {

    private class Node {
        /**
         * 存储Key
         */
        K key;

        /**
         * 存储value
         */
        V value;

        /**
         * 左孩子
         */
        Node left;
        /**
         * 右孩子
         */
        Node right;

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

        Node() {
        }
    }

    /**
     * 根节点
     */
    private Node root;
    /**
     * map的大小
     */
    private int size;

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

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

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

    /**
     * 二分搜索树的递归实现
     *
     * @param node  二分搜索树添加的根节点
     * @param key   添加的key
     * @param value 添加的value
     * @return Node 返回添加节点之后的二分搜索树
     */
    private Node add(Node node, K key, V value) {
        if (node == null) {
            size++;
            return new Node(key, value, null, null);
        }
        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);
        }
        return node;
    }

    /**
     * 查看map中是否包含某个键
     *
     * @param key 查看是否重复的键
     * @return true则包含, false则不包含
     */
    public boolean contain(K key) {
        return contain(root, key);
    }

    /**
     * 包含某个键的递归处理
     *
     * @param node 二分搜索树的根节点
     * @param key  查看的键
     * @return true则包含此键, false则不包含
     */
    private boolean contain(Node node, K key) {

        if (node == null) {
            return false;
        }

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

    @Override
    public V remove(K key) {
        V value = get(key);
        root = remove(root, key);

        return value;
    }

    /**
     * 取得最小值
     *
     * @return E 返回最小值
     */
    public K minimum() {
        if (size == 0) {
            throw new IllegalArgumentException("the bst is empty");
        }
        return minimum(root).key;
    }

    /**
     * 取得最小值的递归处理
     *
     * @param node 取得最小值的根节点
     * @return 返回取得的最小值
     */
    private Node minimum(Node node) {
        if (node.left == null) {
            return node;
        }
        return minimum(node.left);
    }

    /**
     * 取得最大值
     *
     * @return E 返回最大值
     */
    public K maximum() {
        if (root == null) {
            throw new IllegalArgumentException("the bst is empty");
        }
        return maximum(root).key;
    }

    /**
     * 取得最大值的递归处理
     *
     * @param node 取得最大值的根节点
     * @return 返回取得的最大值
     */
    private Node maximum(Node node) {
        if (node.right == null) {
            return node;
        }
        return maximum(node.right);
    }

    /**
     * 删除最小值, 并返回删除的元素
     * @return 删除的最小值元素
     */
    public K removeMin() {
        K ref = minimum();
        root = removeMin(root);
        size --;
        return ref;
    }

    /**
     * 删除最小节点的递归处理
     * @param node 根节点
     * @return 返回删除最小节点之后的根节点
     */
    private Node removeMin(Node node) {
        if (node.left == null) {
            Node rightNode = node.right;
            node.right = null;
            return rightNode;
        }
        node.left = removeMin(node.left);
        return node;
    }

    /**
     * 删除最大值, 并返回删除的元素
     * @return 删除的最大值元素
     */
    public K removeMax() {
        K ref = maximum();
        root = removeMax(root);
        size --;
        return ref;
    }

    /**
     * 删除最大节点的递归处理
     * @param node 根节点
     * @return 返回删除最大节点之后的根节点
     */
    private Node removeMax(Node node) {
        if (node.right == null) {
            Node leftNode = node.left;
            node.left = null;
            return leftNode;
        }
        node.right = removeMax(node.right);
        return node;
    }

    /**
     * 删除指定节点的递归处理
     *
     * @param node 要删除的根节点
     * @param key    要删除的元素的键
     * @return 返回删除元素之后的节点
     */
    private Node remove(Node node, K key) {
        if (node == null) {
            return null;
        }
        if (key.compareTo(node.key) < 0) {
            node.left = remove(node.left, key);
        } else if (key.compareTo(node.key) > 0) {
            node.right = remove(node.right, key);
        } else {
            if (node.left == null) {
                Node rightNode = node.right;
                node.right = null;
                size--;
                return rightNode;
            } else if (node.right == null) {
                Node leftNode = node.left;
                node.left = null;
                size--;
                return leftNode;
            } else {
                Node accessor = minimum(node.right);
                accessor.right = removeMin(node.right);
                accessor.left = node.left;
                node.left = node.right = null;
                return accessor;
            }
        }
        return node;
    }

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

    @Override
    public V get(K key) {
        Node node = getNode(root, key);
        return null == node ? null : node.value;
    }

    private Node getNode(Node node, K key) {
        if (node == null) {
            return null;
        }
        if (key.compareTo(node.key) < 0) {
            return getNode(node.left, key);
        } else if (key.compareTo(node.key) > 0){
            return getNode(node.right, key);
        } else {
            return node;
        }
    }
}

两种实现方式对比

package pers.jssd.map;

import java.util.ArrayList;

/**
 * @author jssdjing@gmail.com
 */
public class CompareMap {
    public static void main(String[] args) {
        Map<String,Integer> linkedListMap = new LinkedListMap<>();
        Map<String,Integer> BSTMap = new BSTMap<>();
        CompareMap compareMap = new CompareMap();
        double time1 = compareMap.test(linkedListMap);
        System.out.println("time1 = " + time1);
        double time2 = compareMap.test(BSTMap);
        System.out.println("time2 = " + time2);
    }

    private double test(Map<String, Integer> map) {
        long start = System.nanoTime();
        ArrayList<String> list = new ArrayList<>();
        boolean flag = FileOperation.readFile("pride-and-prejudice.txt", list);
        if (flag) {
            for (String word : list) {
                Integer count = map.get(word);
                if (count == null) {
                    map.add(word, 1);
                } else {
                    map.set(word, count + 1);
                }
            }
            System.out.println("map.getSize() = " + map.getSize());
            System.out.println("map.get(\"pride\") = " + map.get("pride"));
        }
        long end = System.nanoTime();
        return (end-start) / 1000000000.0;
    }
}

LeetCode 中例题解析

349号问题: 两个数组的交集

问题描述: 349. 两个数组的交集

解题代码:

package pers.jssd.leetcode;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        List<Integer> list = new ArrayList<>();
        Set<Integer> set = new TreeSet<>();
        for (int i : nums1) {
            set.add(i);
        }
        for (int i : nums2) {
            if (set.contains(i)) {
                list.add(i);
                set.remove(i);
            }
        }
        int[] ref = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            ref[i] = list.get(i);
        }
        return ref;
    }
}

350号问题

问题描述: 250. 两个数组的交集二

解题代码:

package pers.jssd.leetcode;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * leetCode第349问题
 */
class Solution1 {
    public int[] intersection(int[] nums1, int[] nums2) {
        List<Integer> list = new ArrayList<>();
        Set<Integer> set = new TreeSet<>();
        for (int i : nums1) {
            set.add(i);
        }
        for (int i : nums2) {
            if (set.contains(i)) {
                list.add(i);
                set.remove(i);
            }
        }
        int[] ref = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            ref[i] = list.get(i);
        }
        return ref;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值