package newdata.datastruct.binarytree;
import java.util.ArrayDeque;
import java.util.Objects;
import java.util.Queue;
public class HtqHashMap<K,V> {
private static class Entry<K,V>{
int hash;
boolean color;
K key;
V value;
Entry<K,V> parent;
Entry<K,V> left;
Entry<K,V> right;
private Entry(K key, V value, Entry<K, V> parent) {
this.key = key;
this.value = value;
this.parent = parent;
this.hash = key==null?0:key.hashCode();
}
private boolean isLeftChild(){
if (parent==null) return false;
if (parent.left==this){
return true;
}
return false;
}
private boolean isRightChild(){
if (parent==null) return false;
if (parent.right==this){
return true;
}
return false;
}
private boolean hasTwoChildren(){
return left!=null&&right!=null;
}
private boolean isLeaf(){
return left==null&&right==null;
}
private Entry<K, V> getUncleEntry(){
if (parent==null) return null;
if (parent.isLeftChild()){
return parent.parent.right;
}else if (parent.isRightChild()){
return parent.parent.left;
}else {
return null;
}
}
private Entry<K, V> getBrotherEntry(){
if (isLeftChild()){
return parent.right;
}else if (isRightChild()){
return parent.left;
}else {
return null;
}
}
}
private static final boolean BLACK = true;
private static final boolean RED = false;
private int size;
private Entry<K, V>[] elementData;
private final static float LOAD_FACTOR = 0.75f;
//no Comparetor
public HtqHashMap() {
elementData = new Entry[4<<1];
}
public int size(){
return size;
}
public boolean isEmpty(){
return size==0;
}
public boolean containsKey(K key){
return getEntry(key)!=null;
}
private Entry<K, V> getEntry(K key) {
int hash = key==null?0:key.hashCode();
Entry<K, V> entry = elementData[index(hash)];
return getEntry(entry,key);
}
private int index(int hash) {
return (hash^(hash>>>16))&(elementData.length-1);
}
private Entry<K, V> getEntry(Entry<K, V> entry,K key) {
int hash = key==null?0:key.hashCode();
while (entry!=null){
K k2 = entry.key;
int h2 = entry.hash;
int cmp;
Entry<K, V> result;
if (hash<h2){
entry = entry.left;
}else if (hash>h2){
entry = entry.right;
}else if (Objects.equals(key,k2)){
return entry;
}else if (key!=null&&k2!=null&&
key.getClass()==k2.getClass()&&
key instanceof Comparable&&
(cmp=(((Comparable<K>)key).compareTo(k2)))!=0){
if (cmp<0){
entry = entry.left;
}else {
entry =entry.right;
}
}else if (entry.left!=null&&(result=getEntry(entry.left,key))!=null){
return result;
}else {
entry = entry.right;
}
}
return null;
}
public boolean containsValue(V value){
if (size == 0) return false;
Queue<Entry<K,V>> queue = new ArrayDeque<>();
for (int i=0;i<elementData.length;i++){
Entry<K,V> entry = elementData[i];
if (entry==null) continue;
queue.offer(entry);
while (!queue.isEmpty()){
Entry<K, V> poll = queue.poll();
if (Objects.equals(poll.value,value)){
return true;
}
if (poll.left!=null){
queue.offer(poll.left);
}
if (poll.right!=null){
queue.offer(poll.right);
}
}
}
return false;
}
public void clear(){
if (size == 0) return;
for (int i=0;i<elementData.length;i++){
elementData[i] = null;
}
size = 0;
}
public void put(K key,V value){
ensureCapacity();
int hash = key==null?0:key.hashCode();
Entry<K,V> entry = elementData[index(hash)];
if (entry==null){
entry = new Entry<>(key,value,null);
elementData[index(hash)] = entry;
size++;
afterPut(entry);
return;
}
Entry<K,V> parent = null;
int cmp = 0;
Entry<K,V> result = null;
boolean search = false;
while (entry!=null){
parent = entry;
K k2 = entry.key;
int h2 = entry.hash;
if (hash<h2){
cmp = -1;
}else if (hash>h2){
cmp = 1;
}else if (Objects.equals(key,k2)){
cmp = 0;
}else if (key!=null&&k2!=null&&key.getClass()==k2.getClass()&&
key instanceof Comparable&&(cmp = ((Comparable)key).compareTo(k2))!=0){
}else if (search){
cmp = System.identityHashCode(key) - System.identityHashCode(k2);
}else {
if (entry.left!=null&&(result=getEntry(entry.left,key))!=null||
entry.right!=null&&(result=getEntry(entry.right,key))!=null) {
entry = result;
cmp = 0;
}else {
search = true;
cmp = System.identityHashCode(key) - System.identityHashCode(k2);
}
}
if (cmp<0){
entry = entry.left;
}else if (cmp>0){
entry = entry.right;
}else {
entry.hash = hash;
entry.key = key;
entry.value = value;
return;
}
}
Entry<K,V> newEntry = new Entry<>(key,value,parent);
if (cmp<0){
parent.left = newEntry;
}else if (cmp>0){
parent.right = newEntry;
}
size++;
afterPut(newEntry);
}
private void ensureCapacity() {
if ((size/elementData.length)>LOAD_FACTOR){
grow();
}
}
private void grow() {
Entry<K,V>[] oldElementData = elementData;
elementData = new Entry[oldElementData.length<<1];
for (int i=0;i<oldElementData.length;i++){
Entry<K,V> entry = oldElementData[i];
if (entry==null) continue;
Queue<Entry<K,V>> queue = new ArrayDeque<>();
queue.offer(entry);
while (!queue.isEmpty()){
Entry<K, V> poll = queue.poll();
if (poll.left!=null){
queue.offer(poll.left);
}
if (poll.right!=null){
queue.offer(poll.right);
}
moveEntry(poll);
}
}
}
private void moveEntry(Entry<K,V> poll) {
poll.parent = null;
poll.left = null;
poll.right = null;
poll.color = RED;
K key = poll.key;
V value = poll.value;
int hash = poll.hash;
Entry<K,V> entry = elementData[index(hash)];
if (entry==null){
entry = poll;
elementData[index(hash)] = entry;
afterPut(entry);
return;
}
Entry<K,V> parent = null;
int cmp = 0;
while (entry!=null){
parent = entry;
K k2 = entry.key;
int h2 = entry.hash;
if (hash<h2){
cmp = -1;
}else if (hash>h2){
cmp = 1;
}else if (key!=null&&k2!=null&&key.getClass()==k2.getClass()&&
key instanceof Comparable&&(cmp = ((Comparable)key).compareTo(k2))!=0){
}else {
cmp = System.identityHashCode(key) - System.identityHashCode(k2);
}
if (cmp<0){
entry = entry.left;
}else if (cmp>0){
entry = entry.right;
}
}
poll.parent = parent;
if (cmp<0){
parent.left = poll;
}else if (cmp>0){
parent.right = poll;
}
afterPut(poll);
}
private void afterPut(Entry<K, V> entry) {
if (entry.parent==null){
blackColor(entry);
return;
}
if (isBlack(entry.parent)){
return;
}
Entry<K, V> uncle = entry.getUncleEntry();
Entry<K, V> parent = entry.parent;
if (isRed(uncle)){
blackColor(parent);
blackColor(uncle);
afterPut(redColor(parent.parent));
}else {
Entry<K, V> grand = entry.parent.parent;
if (parent.isLeftChild()){
if (entry.isLeftChild()){
blackColor(parent);
redColor(grand);
rightRotate(grand);
}else {
blackColor(entry);
redColor(grand);
leftRotate(parent);
rightRotate(grand);
}
}else {
if (entry.isLeftChild()){
blackColor(entry);
redColor(grand);
rightRotate(parent);
leftRotate(grand);
}else {
blackColor(parent);
redColor(grand);
leftRotate(grand);
}
}
}
}
private void rightRotate(Entry<K,V> grand) {
Entry<K,V> parent = grand.left;
Entry<K,V> entry = parent.right;
grand.left = entry;
parent.right = grand;
parent.parent = grand.parent;
if (grand.isLeftChild()){
grand.parent.left = parent;
}else if (grand.isRightChild()){
grand.parent.right = parent;
}else {
elementData[index(grand.hash)] = parent;
}
if (entry!=null){
entry.parent = grand;
}
grand.parent = parent;
}
private void leftRotate(Entry<K,V> grand) {
Entry<K,V> parent = grand.right;
Entry<K,V> entry = parent.left;
grand.right = entry;
parent.left = grand;
parent.parent = grand.parent;
if (grand.isLeftChild()){
grand.parent.left = parent;
}else if (grand.isRightChild()){
grand.parent.right = parent;
}else {
elementData[index(grand.hash)] = parent;
}
if (entry!=null){
entry.parent = grand;
}
grand.parent = parent;
}
private Entry<K, V> blackColor(Entry<K, V> entry){
if (entry==null) return null;
entry.color = BLACK;
return entry;
}
private Entry<K, V> redColor(Entry<K, V> entry){
if (entry==null) throw new IllegalArgumentException();
entry.color = RED;
return entry;
}
private boolean isBlack(Entry<K, V> entry){
if (entry==null) return true;
if (entry.color==BLACK){
return true;
}
return false;
}
private boolean isRed(Entry<K, V> entry){
if (entry==null) return false;
if (entry.color==RED){
return true;
}
return false;
}
public V remove(K key){
Entry<K, V> entry = getEntry(key);
V v = entry.value;
if (entry.hasTwoChildren()){
Entry<K, V> post = postNode(entry);
entry.hash = post.hash;
entry.key = post.key;
entry.value = post.value;
entry = post;
}
if (entry.isLeaf()){
if (entry.isLeftChild()){
entry.parent.left = null;
}else if (entry.isRightChild()){
entry.parent.right = null;
}else {
elementData[index(entry.hash)] = null;
}
}else {
Entry<K, V> replace = entry.left==null?entry.right:entry.left;
replace.parent = entry.parent;
if (entry.isLeftChild()){
entry.parent.left = replace;
}else if (entry.isRightChild()){
entry.parent.right = replace;
}else {
elementData[index(entry.hash)] = replace;
}
entry = replace;
}
size--;
afterRemove(entry);
return v;
}
private void afterRemove(Entry<K,V> entry) {
if (isRed(entry)){
blackColor(entry);
return;
}
if (entry.parent==null){
blackColor(entry);
return;
}
Entry<K, V> parent = entry.parent;
Entry<K, V> brother = (parent.left==null||parent.left==entry)?parent.right:parent.left;
boolean pColor = parent.color;
if (brother.isLeftChild()){
if (isRed(brother)){
blackColor(brother);
redColor(parent);
rightRotate(parent);
brother = parent.left;
}
if (isRed(brother.left)||isRed(brother.right)){
if (isBlack(brother.left)&&isRed(brother.right)){
leftRotate(brother);
brother = parent.left;
}
brother.color = pColor;
blackColor(brother.left);
blackColor(parent);
rightRotate(parent);
}else {
blackColor(parent);
redColor(brother);
if (pColor){
afterRemove(parent);
}
}
}else {
if (isRed(brother)){
blackColor(brother);
redColor(parent);
leftRotate(parent);
brother = parent.right;
}
if (isRed(brother.left)||isRed(brother.right)){
if (isBlack(brother.right)&&isRed(brother.left)){
rightRotate(brother);
brother = parent.right;
}
brother.color = pColor;
blackColor(brother.right);
blackColor(parent);
leftRotate(parent);
}else {
blackColor(parent);
redColor(brother);
if (pColor){
afterRemove(parent);
}
}
}
}
private Entry<K, V> preNode(Entry<K, V> entry){
Entry<K, V> left = entry.left;
if (left!=null){
while (left.right!=null){
left = left.right;
}
return left;
}
Entry<K, V> parent = entry.parent;
while (parent!=null&&parent.isLeftChild()){
parent = parent.parent;
}
return parent;
}
private Entry<K, V> postNode(Entry<K, V> entry){
Entry<K, V> right = entry.right;
if (right!=null){
while (right.left!=null){
right = right.left;
}
return right;
}
Entry<K, V> parent = entry.parent;
while (parent!=null&&parent.isRightChild()){
parent = parent.parent;
}
return parent;
}
public V get(K key){
Entry<K, V> entry = getEntry(key);
if (entry==null) return null;
return entry.value;
}
public void print(){
for (int i=0;i<elementData.length;i++){
StringBuilder stringBuilder = new StringBuilder();
Entry<K,V> entry = elementData[i];
print(entry,stringBuilder,"");
System.out.println(stringBuilder);
System.out.println("-------------------------------------------");
}
}
private StringBuilder print(Entry<K,V> entry,StringBuilder stringBuilder,String fix){
if (entry==null) return stringBuilder;
print(entry.left,stringBuilder,fix+"L--->");
stringBuilder.append(fix);
if (entry.color){
stringBuilder.append("["+entry.key+"_"+entry.value+"]").append("\n");
}else {
stringBuilder.append("[R_"+entry.key+"_"+entry.value+"]").append("\n");
}
print(entry.right,stringBuilder,fix+"R--->");
return stringBuilder;
}
}
数据结构之HashMap
最新推荐文章于 2022-09-08 19:13:38 发布