映射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;
}
}