哈希表、什么是哈希表、哈希冲突的处理(连地址法)、动态空间

版权声明:版权声明:本文为博主原创文章,转载时请注明出处——作者:冰怜 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;
		
	}

 

另一种更加优化的问题

列一个素数数组、其实很简单,加个边界判断是否越界,增加空间就++,缩小就--

猜你喜欢

转载自blog.csdn.net/xiaoxin0630/article/details/87897880