版权声明:版权声明:本文为博主原创文章,转载时请注明出处——作者:冰怜 https://blog.csdn.net/xiaoxin0630/article/details/87897880
什么是哈希表
我们先来看一到力扣很简单题
class Solution {
public int firstUniqChar(String s) {
int[] freq = new int[26];
for(int i = 0 ; i < s.length() ; i ++)
freq[s.charAt(i) - 'a'] ++;
for(int i = 0 ; i < s.length() ; i ++)
if(freq[s.charAt(i) - 'a'] == 1)
return i;
return -1;
}
}
freq就是哈希表
每个字符都和一个索引相对应
哈希表
“键”转换为“索引”
哈希函数的设计
整数和大整数设计
可以用取模
大整数
简单的解决方法:模一个素数、
只需要记住就行,没必要往下深入理解,有兴趣可以深入数论
最终的哈希公式
hash(code)=((((c%M)*B+o)%M*B+d)%M*B+e)%M
浮点型
字符串
最终的公式和伪代码
复合类型
重写的hash和equals
@Override
public int hashCode(){
int B=31;
int hash=0;
hash = hash*B+grade;
hash = hash*B+cls;
hash = hash*B+firstName.toLowerCase().hashCode();//转为小写
hash = hash*B+lastName.toLowerCase().hashCode();
return hash;
}
@Override
public boolean equals(Object o){
if(this == o)
return true;
if(o== null)
return false;
if(getClass() !=o.getClass())
return false;
Student another=(Student)o;
return this.grade==another.grade &&
this.cls ==another.cls &&
this.firstName.toLowerCase().equals(another.firstName.toLowerCase()) && this.lastName.toLowerCase().equals(another.lastName.toLowerCase());
}
哈希冲突的处理——链地址法
(hashCode(k1) & 0x7fffffff)%M
然后我们创建我们哈希表代码
//生成素数键
private int hash(K key){
return (key.hashCode() & 0x7fffffff)%M;
}
import java.util.TreeMap;
public class HashTable<K, V> {
private TreeMap<K, V>[] hashtable;
private int size;
private int M;
public HashTable(int M){
this.M = M;
size = 0;
hashtable = new TreeMap[M];
for(int i = 0 ; i < M ; i ++)
hashtable[i] = new TreeMap<>();
}
public HashTable(){
this(97);
}
private int hash(K key){
return (key.hashCode() & 0x7fffffff) % M;
}
public int getSize(){
return size;
}
public void add(K key, V value){
TreeMap<K, V> map = hashtable[hash(key)];
if(map.containsKey(key))
map.put(key, value);
else{
map.put(key, value);
size ++;
}
}
public V remove(K key){
V ret = null;
TreeMap<K, V> map = hashtable[hash(key)];
if(map.containsKey(key)){
ret = map.remove(key);
size --;
}
return ret;
}
public void set(K key, V value){
TreeMap<K, V> map = hashtable[hash(key)];
if(!map.containsKey(key))
throw new IllegalArgumentException(key + " doesn't exist!");
map.put(key, value);
}
public boolean contains(K key){
return hashtable[hash(key)].containsKey(key);
}
public V get(K key){
return hashtable[hash(key)].get(key);
}
}
哈希表动态空间处理
N/M >= upperTol
N/M < lowerTol
两种情况的代码实现
增加空间
public void add(K key,V value){
TreeMap<K, V> map=hashtable[hash(key)];
if(map.containsKey(key))
map.put(key, value);
else{
map.put(key, value);
size++;
if(size >=upperTol * M)
resize(2*M);
}
// if(hashtable[hash(key)].containsKey(key))//查找是否存在key
// hashtable[hash(key)].put(key, value);
// else{
// hashtable[hash(key)].put(key, value);
// size++;
// }
}
减少空间
public V remove(K key){
TreeMap<K, V> map=hashtable[hash(key)];
V ret=null;
if(map.containsKey(key)){
ret=map.remove(key);
size--;
if(size <lowerTol * M && M/2 >=initCapacity)
resize(M/2);
}
return ret;
}