哈希表
哈希表的几个特殊应用实现:
1.* 设计一个数据结构,使得该结构再插入,删除和随机获取结构中的数据的时间复杂度均为O(1)
1 public class RandomPools { 2 public static class Pool<K> { 3 HashMap<K,Integer> keyIndexMap; 4 HashMap<Integer,K> indexKeyMap; 5 int size; 6 7 public Pool() { 8 keyIndexMap = new HashMap<>(); 9 indexKeyMap = new HashMap<>(); 10 size = 0; 11 } 12 13 public void insert(K key) { 14 if (!keyIndexMap.containsKey(key)) { 15 keyIndexMap.put(key, size); 16 indexKeyMap.put(size++, key); 17 } 18 } 19 20 public void delete(K key) {//将要删的那个值移到最后再删除 21 if (keyIndexMap.containsKey(key)) { 22 int deleteIndex = keyIndexMap.get(key); 23 int lastIndex = --size; 24 K lastKey = indexKeyMap.get(lastIndex); 25 keyIndexMap.put(lastKey, deleteIndex); 26 indexKeyMap.put(deleteIndex, lastKey); 27 keyIndexMap.remove(key); 28 indexKeyMap.remove(lastIndex); 29 } 30 } 31 32 public K getRandom() { 33 if (this.size == 0) { 34 return null; 35 } 36 int randomIndex = (int)(Math.random() * this.size); 37 return indexKeyMap.get(randomIndex); 38 } 39 } 40 }
2. 位图:对于只要用两种状态就可以表示的信息,可以用一位来表示(即无需用int,long等类型,造成不必要空间浪费)
1 public static void main(String[] args) { 2 int[] nums = new int[10];//10 * 32bit -> 320bit 3 4 int i = 178;//获取第178bit上的位值(为0还是1) 5 6 int numIndex = i / 32;//确定该位在哪个int类型的数当中 7 int bitIndex = i % 32;//确定在int类型数中的哪个位置 8 9 //获取该位的信息 10 int s = (nums[numIndex] >> bitIndex) & 1; 11 12 System.out.println(s); 13 14 //将该位的信息置1 15 nums[numIndex] = nums[numIndex] | (1 << bitIndex); 16 17 //将该位的信息置0 18 nums[numIndex] = nums[numIndex] & (~(1 << bitIndex)); 19 }
3.布隆过滤器:
用于判断该值是否处在所要过滤的范围内
* 构建一个长度为m的位图,将所有要过滤的数据进行遍历记录:
* 建立过滤范围:将每个数据通过多个Hash函数得到多个哈希值,并%m,将得到的所有值在位图上做一个标记。
* 遍历完所有的数据并依次进行标记。
* 标记完位图后,即可用该位图判断其他数据是否是在过滤的范围内:用同样的多个哈希函数得到多个哈希值,如果这些
* 哈希值全部被标记过,则认为该数据为要过滤的数据,否则则认为不是要过滤的数据
*
* 特点:
* 1.一定不会把要过滤的数据认为成不要过滤的,但可能会把不要过滤的数据认为成要过滤的。
* 2.发生差错的可能与位图的长度m和Hash函数的个数k有关
* m越大发生差错的可能性越低,但可能性的减小速率随着m的增大逐渐降低
* k存在一个中间极值点,使得在该点差错可能性恰好达到最低