package com.mjy.map; import com.mjy.printer.BinaryTreeInfo; import com.mjy.printer.BinaryTrees; import java.util.LinkedList; import java.util.Objects; import java.util.Queue; /** * *************************************************** * * @ClassName HashMap * @Description 描述 * @Author maojianyun * @Date 2020/1/10 13:53 * @Version V1.0 **************************************************** **/ @SuppressWarnings({ "unchecked", "unused" }) public class HashMap<K, V> implements Map<K, V> { private final static boolean RED = false; private final static boolean BLACK = true; private Node<K, V>[] table; private int size; private static final int DEFAULT_CAPACITY = 1 << 4; private static final float DEFAULT_LOAD_FACTOR = 0.75f; public HashMap() { table = new Node[DEFAULT_CAPACITY]; } public int size() { return size; } public boolean isEmpty() { return size == 0; } public void clear() { if (size == 0) { return; } size = 0; for (int i = 0; i < table.length; i++) { table[i] = null; } } public V put(K key, V value) { resize(); int index = index(key); // 取出index位置的红黑树根节点 Node<K, V> root = table[index]; if (root == null) { root = new Node<K, V>(key, value, null); table[index] = root; size++; // 修复红黑树性质 afterPut(root); return null; } // 添加新的节点到红黑树上面 Node<K, V> parent = root; Node<K, V> node = root; int cmp = 0; K k1 = key; int h1 = k1 == null ? 0 : k1.hashCode(); Node<K, V> result = null; boolean searched = false; // 是否已经搜索过这个key do { parent = node; K k2 = node.key; int h2 = node.hash; if (h1 > h2) { cmp = 1; } else if (h1 < h2) { cmp = -1; } else if (Objects.equals(k1, k2)) { cmp = 0; } else if (k1 != null && k2 != null && k1.getClass() == k2.getClass() && k1 instanceof Comparable && (cmp = ((Comparable<K>) k1).compareTo(k2)) != 0) { } else if (searched) { // 已经扫描了 cmp = System.identityHashCode(k1) - System.identityHashCode(k2); } else { if ((node.left != null && (result = node(node.left, k1)) != null) || (node.right != null && (result = node(node.right, k1)) != null)) { // 已经存在这个key node = result; cmp = 0; } else { // 不存在这个key searched = true; cmp = System.identityHashCode(k1) - System.identityHashCode(k2); } } if (cmp > 0) { node = node.right; } else if (cmp < 0) { node = node.left; } else { // 相等 V oldValue = node.value; node.key = key; node.value = value; node.hash = h1; return oldValue; } } while (node != null); Node<K, V> newNode = new Node<K, V>(key, value, parent); if (cmp > 0) { parent.right = newNode; } else { parent.left = newNode; } size++; afterPut(newNode); return null; } public V get(K key) { Node<K, V> node = node(key); return node != null ? node.value : null; } public V remove(K key) { return remove(node(key)); } public boolean containsKey(K key) { return node(key) != null; } public boolean containsValue(V value) { if (size == 0) { return false; } for (int i = 0; i < table.length; i++) { if (table[i] == null) { continue; } Queue<Node<K, V>> queue = new LinkedList<>(); queue.offer(table[i]); while (!queue.isEmpty()) { Node<K, V> node = queue.poll(); if (Objects.equals(value, node.value)) { return true; } if (node.left != null) { queue.offer(node.left); } if (node.right != null) { queue.offer(node.right); } } } return false; } public void traversal(Visitor<K, V> visitor) { if (size == 0 || visitor.stop) { return; } Queue<Node<K, V>> queue = new LinkedList<>(); for (int i = 0; i < table.length; i++) { if (table[i] == null) { continue; } queue.offer(table[i]); while (!queue.isEmpty()) { Node<K, V> node = queue.poll(); visitor.stop = visitor.visit(node.key, node.value); if (node.left != null) { queue.offer(node.left); } if (node.right != null) { queue.offer(node.right); } } } } /** * 删除node * * @param node * @return */ private V remove(Node<K, V> node) { if (node == null) { return null; } V oldValue = node.value; if (node.hasTwoChildren()) { // 度为2的节点 // 找到后继节点 Node<K, V> su = successor(node); // 用后继节点的值覆盖度为2的节点的值 node.key = su.key; node.value = su.value; node.hash = su.hash; // 删除后继节点 node = su; } // 删除node节点(node的度必然是1或者0) // 如果度为1、则返回的是其子节点 Node<K, V> replacement = node.left != null ? node.left : node.right; int index = index(node); if (replacement != null) { // 删除度为1的节点 replacement.parent = node.parent; if (node.parent == null) { table[index] = replacement; } else if (node.isLeftChild()) { node.parent.left = replacement; } if (node.isRightChild()) { node.parent.right = replacement; } // 删除节点之后的处理 afterRemove(replacement); } else if (node.parent == null) { // node是叶子节点并且是根节点 table[index] = null; } else { // node是叶子节点,但不是根节点 if (node == node.parent.left) { node.parent.left = null; } else { // node == node.parent.right node.parent.right = null; } // 删除节点之后的处理 afterRemove(node); } size--; return oldValue; } private void resize() { // 装填因子 <= 0.75 if (size / table.length <= DEFAULT_LOAD_FACTOR) { return; } Node<K, V> [] oldTable = table; table = new Node[oldTable.length << 1]; Queue<Node<K, V>> queue = new LinkedList<Node<K,V>>(); for(int i = 0; i < oldTable.length; i++) { if (oldTable[i] == null) { continue; } queue.offer(oldTable[i]); while(!queue.isEmpty()) { Node<K, V> node = queue.poll(); if (node.left != null) { queue.offer(node.left); } if (node.right != null) { queue.offer(node.right); } // 挪动代码得放到最后面 moveNode(node); } } } private void moveNode(Node<K, V> newNode) { // 重置 newNode.parent = null; newNode.left = null; newNode.right = null; newNode.color = RED; int index = index(newNode); // 取出index位置的红黑树根节点 Node<K, V> root = table[index]; if (root == null) { root = newNode; table[index] = root; afterPut(root); return; } // 添加新的节点到红黑树上面 Node<K, V> parent = root; Node<K, V> node = root; int cmp = 0; K k1 = newNode.key; int h1 = newNode.hash; do { parent = node; K k2 = node.key; int h2 = node.hash; if (h1 > h2) { cmp = 1; } else if (h1 < h2) { cmp = -1; } else if (k1 != null && k2 != null && k1 instanceof Comparable && k1.getClass() == k2.getClass() && (cmp = ((Comparable<K>)k1).compareTo(k2)) != 0) { } else { cmp = System.identityHashCode(k1) - System.identityHashCode(k2); } if (cmp > 0) { node = node.right; } else if (cmp < 0) { node = node.left; } } while (node != null); // 看看插入到父节点的哪个位置 newNode.parent = parent; if (cmp > 0) { parent.right = newNode; } else { parent.left = newNode; } // 新添加节点之后的处理 afterPut(newNode); } /** * 得到节点的后继节点 * * @param node * @return */ private Node<K, V> successor(Node<K, V> node) { if (node == null) return null; // 前驱节点在左子树当中(right.left.left.left....) Node<K, V> p = node.right; if (p != null) { while (p.left != null) { p = p.left; } return p; } // 从父节点、祖父节点中寻找前驱节点 while (node.parent != null && node == node.parent.right) { node = node.parent; } return node.parent; } private Node<K, V> node(K key) { Node<K, V> root = table[index(key)]; return root == null ? null : node(root, key); } private Node<K, V> node(Node<K, V> node, K k1) { int h1 = k1 == null ? 0 : k1.hashCode(); // 存储查找结果 Node<K, V> result = null; int cmp = 0; while (node != null) { K k2 = node.key; int h2 = node.hash; // 先比较哈希值 if (h1 > h2) { node = node.right; } else if (h1 < h2) { node = node.left; } else if (Objects.equals(k1, k2)) { return node; } else if (k1 != null && k2 != null && k1.getClass() == k2.getClass() && k1 instanceof Comparable && (cmp = ((Comparable<K>) k1).compareTo(k2)) != 0) { node = cmp > 0 ? node.right : node.left; } else if (node.right != null && (result = node(node.right, k1)) != null) { return result; } else { // 只能往左边找 node = node.left; } } return null; } /** * 得到hash索引(在数组中的索引下标) * * @param key * @return */ private int index(K key) { if (key == null) { return 0; } int hash = key.hashCode(); hash = hash ^ (hash >>> 16); return hash & (table.length - 1); } private int index(Node<K, V> node) { if (node == null) { return 0; } int hash = node.hash; hash = hash ^ (hash >>> 16); return hash & (table.length - 1); } private void afterPut(Node<K, V> node) { Node<K, V> parent = node.parent; // 添加的是根节点 或者 上溢到达了根节点 if (parent == null) { black(node); return; } // 如果父节点是黑色,直接返回 if (isBlack(parent)) { return; } // 叔父节点 Node<K, V> uncle = parent.sibling(); // 祖父节点 Node<K, V> grand = red(parent.parent); if (isRed(uncle)) { // 叔父节点是红色【B树节点上溢】 black(parent); black(uncle); // 把祖父节点当做是新添加的节点 afterPut(grand); return; } // 叔父节点不是红色 if (parent.isLeftChild()) { // L if (node.isLeftChild()) { // LL black(parent); } else { // LR black(node); rotateLeft(parent); } rotateRight(grand); } else { // R if (node.isLeftChild()) { // RL black(node); rotateRight(parent); } else { // RR black(parent); } rotateLeft(grand); } } private void afterRemove(Node<K, V> node) { // 如果删除的节点是红色 // 或者 用以取代删除节点的子节点是红色 if (isRed(node)) { black(node); return; } Node<K, V> parent = node.parent; if (parent == null) { return; } // 删除的是黑色叶子节点【下溢】 // 判断被删除的node是左还是右 boolean left = parent.left == null || node.isLeftChild(); Node<K, V> sibling = left ? parent.right : parent.left; if (left) { // 被删除的节点在左边,兄弟节点在右边 if (isRed(sibling)) { // 兄弟节点是红色 black(sibling); red(parent); rotateLeft(parent); // 更换兄弟 sibling = parent.right; } // 兄弟节点必然是黑色 if (isBlack(sibling.left) && isBlack(sibling.right)) { // 兄弟节点没有1个红色子节点,父节点要向下跟兄弟节点合并 boolean parentBlack = isBlack(parent); black(parent); red(sibling); if (parentBlack) { afterRemove(parent); } } else { // 兄弟节点至少有1个红色子节点,向兄弟节点借元素 // 兄弟节点的左边是黑色,兄弟要先旋转 if (isBlack(sibling.right)) { rotateRight(sibling); sibling = parent.right; } color(sibling, colorOf(parent)); black(sibling.right); black(parent); rotateLeft(parent); } } else { // 被删除的节点在右边,兄弟节点在左边 if (isRed(sibling)) { // 兄弟节点是红色 black(sibling); red(parent); rotateRight(parent); // 更换兄弟 sibling = parent.left; } // 兄弟节点必然是黑色 if (isBlack(sibling.left) && isBlack(sibling.right)) { // 兄弟节点没有1个红色子节点,父节点要向下跟兄弟节点合并 boolean parentBlack = isBlack(parent); black(parent); red(sibling); if (parentBlack) { afterRemove(parent); } } else { // 兄弟节点至少有1个红色子节点,向兄弟节点借元素 // 兄弟节点的左边是黑色,兄弟要先旋转 if (isBlack(sibling.left)) { rotateLeft(sibling); sibling = parent.left; } color(sibling, colorOf(parent)); black(sibling.left); black(parent); rotateRight(parent); } } } /** * 给指定节点染指定的颜色 * * @param node 节点 * @param color 颜色 * @return 节点 */ private Node<K, V> color(Node<K, V> node, boolean color) { if (node != null) { node.color = color; } return node; } /** * 节点染成红色 * * @param node * @return */ private Node<K, V> red(Node<K, V> node) { return color(node, RED); } /** * 节点染成黑色 * * @param node * @return */ private Node<K, V> black(Node<K, V> node) { return color(node, BLACK); } /** * 得到节点的颜色 * * @param node * @return */ private boolean colorOf(Node<K, V> node) { return node == null ? BLACK : node.color; } /** * 是否是黑色 * * @param node * @return */ private boolean isBlack(Node<K, V> node) { return colorOf(node) == BLACK; } /** * 是否是红色 * * @param node * @return */ private boolean isRed(Node<K, V> node) { return colorOf(node) == RED; } private void rotateLeft(Node<K, V> grand) { Node<K, V> parent = grand.right; Node<K, V> child = parent.left; grand.right = child; parent.left = grand; afterRotate(grand, parent, child); } private void rotateRight(Node<K, V> grand) { Node<K, V> parent = grand.left; Node<K, V> child = parent.right; grand.left = child; parent.right = grand; afterRotate(grand, parent, child); } private void afterRotate(Node<K, V> grand, Node<K, V> parent, Node<K, V> child) { // 让parent称为子树的根节点 parent.parent = grand.parent; if (grand.isLeftChild()) { grand.parent.left = parent; } else if (grand.isRightChild()) { grand.parent.right = parent; } else { // grand是root节点 table[index(grand.key)] = parent; } // 更新child的parent if (child != null) { child.parent = grand; } // 更新grand的parent grand.parent = parent; } /** * *************************************************** * * @ClassName Node<K , V> * @Description 红黑树节点 * @Author maojianyun * @Date 2020/1/9 22:06 * @Version V1.0 **************************************************** **/ private static class Node<K, V> { // 默认为红色 boolean color = RED; int hash; K key; V value; Node<K, V> left; Node<K, V> right; Node<K, V> parent; public Node(K key, V value, Node<K, V> parent) { this.key = key; this.hash = key == null ? 0 : key.hashCode(); this.value = value; this.parent = parent; } /** * 是否是叶子节点 * * @return */ public boolean isLeaf() { return left == null && right == null; } /** * 是否有两个孩子 * * @return */ public boolean hasTwoChildren() { return left != null && right != null; } /** * 是否是左孩子 * * @return */ public boolean isLeftChild() { return parent != null && this == parent.left; } /** * 是否是右孩子 * * @return */ public boolean isRightChild() { return parent != null && this == parent.right; } /** * 得到兄弟节点 * * @return */ public Node<K, V> sibling() { if (isLeftChild()) { return parent.right; } if (isRightChild()) { return parent.left; } return null; } @Override public String toString() { return color + "_Node_" + key + "_" + value; } } public void print() { if (size == 0) return; for (int i = 0; i < table.length; i++) { final Node<K, V> root = table[i]; System.out.println("【index = " + i + "】"); BinaryTrees.println(new BinaryTreeInfo() { @Override public Object string(Object node) { return node; } @Override public Object root() { return root; } @Override public Object right(Object node) { return ((Node<K, V>) node).right; } @Override public Object left(Object node) { return ((Node<K, V>) node).left; } }); System.out.println("---------------------------------------------------"); } } }
最近下载更多
matintalorr LV10
2021年8月31日
17600446733 LV21
2020年6月23日
2650343087 LV6
2020年5月26日
wyyxhzzp LV1
2020年2月18日
宇1314520乔 LV1
2020年1月31日
dajian LV1
2020年1月18日
最代码官方 LV168
2020年1月16日
最近浏览更多
3334004690 LV10
3月6日
如果不曾相遇 LV3
2023年5月6日
我爱你野狼123
2023年3月22日
暂无贡献等级
woaini12788 LV7
2022年1月17日
ooooops
2022年1月11日
暂无贡献等级
luozf1990 LV3
2022年1月4日
matintalorr LV10
2021年8月31日
絮落无痕 LV13
2021年4月21日
孤独の王者 LV6
2021年4月17日
蹦迪的小熊 LV5
2021年4月8日