哈希函数哈希表小结

哈希函数又称散列函数、离散函数

实现哈希函数的形式有很多种,常见的有MD5、SHA1等加密算法

性质:

    1.输入域无穷,输出域有限 (java中hashCode返回值为int(-2^31~2^31-1)

    2哈希函数不是随机函数

相同的输入值输出一定相同  same input ,same output

    3.哈希碰撞:因为输入域是无限大,输出域是有限的就会导致不同的输入可能会映射相同的输出

 Different input maybe same output

    4.离散性: 比如Input(0,99999)、output{0,1,2,3}其中在output集合中的0、1、2、3会几乎均匀分布

虽然输入域无穷大,输出域S有限集,但是不同的输入如果映射到S有限集上,在整个S域上得到的返回值几乎均匀分布(均匀性越好,离散性越好,哈希函数越优良)

    离散性作用:打破输入规律 –>很相似的东西经过哈希函数后千差万别

    java1/java2/java3输出的结果截然不同:比如返回值为:10、 100w、10亿等

    延伸:如果哈希函数的返回值在S域上均匀分布,那么在S%m在(0,m-1)域上也均匀分布

哈希表

    哈希表亦称散列表,是根据关键码值(Key value)而直接进行访问的数据结构. 

    假设放的字符串是”java”, 哈希值result是:2^30

    假设哈希表长度为17. result%17=13放到哈希表的第(13-1)号位置.如果还有其他字符串str存的位置与字符串java一样时,则以链表的形式把str放置字符串 java后面,随着字符串存入的key增多,哈希链表的长度均匀上涨,当超过一定数量时,则哈希表会进行成倍扩容。但由于哈希表相同key的数据以链表的存储,查找慢,jdk1.8及以后HashMap引入了红黑树TreeMap结构

    另外其实hashSet(key) hashMap(key +value)结构一样,value只是key的一个伴随数据而已.

Hash函数在面试上增删改查都认为是O(1)的操作即默认常数时间,但常数项比较大(因为哈希函数在计算的时候代价有点高)

hashMap常见API操作

package com.se.algorithm;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import java.util.Map.Entry;


public class Code_HashMap {

public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put("wan", "22");
        //是否包含
System.out.println(map.containsKey("wan"));
System.out.println(map.containsKey("lingfeng"));
System.out.println("=========================");
        //通过键取值
System.out.println(map.get("wan"));
System.out.println(map.get("lingfeng"));
System.out.println("=========================");
        //是否为空、集合大小
System.out.println(map.isEmpty());
System.out.println(map.size());
System.out.println("=========================");
        //移除并返回键对应的值
System.out.println(map.remove("wan"));
System.out.println(map.containsKey("wan"));
System.out.println(map.get("wan"));
System.out.println(map.isEmpty());
System.out.println(map.size());
System.out.println("=========================");

map.put("wan", "22");
System.out.println(map.get("wan"));
map.put("wan", "32");
System.out.println(map.get("wan"));

System.out.println("=========================");


map.put("wan", "22");
map.put("ling", "32");
map.put("feng", "33");
        //map无序存储遍历键
for (String key : map.keySet()) {
System.out.println(key);
}
System.out.println("=========================");
        //通过键对应遍历值
for (String values : map.values()) {
System.out.println(values);
}
System.out.println("=========================");
        //清空并添加
map.clear();
map.put("A", "1");
map.put("B", "2");
map.put("C", "3");
map.put("D", "1");
map.put("E", "2");
map.put("F", "3");
map.put("G", "1");
map.put("H", "2");
map.put("I", "3");
//通过键值对获取键值数值
for (Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "," + value);
}
System.out.println("=========================");
        //把要删除的元素存入集合然后放入大集合删除
//或者用迭代器it.remove() ,直接在循环中遍历操作集合元素会报错
List<String> removeKeys = new ArrayList<String>();
for (Entry<String, String> entry : map.entrySet()) {
if (!entry.getValue().equals("1")) {
removeKeys.add(entry.getKey());
}
}
for (String removeKey : removeKeys) {
map.remove(removeKey);
}
for (Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "," + value);
}
System.out.println("=========================");
}

}

练习

      设计RandomPool结构,在该结构中有如下三个功能:

      insert(key):将某个key加入到该结构,做到不重复加入。

      delete(key):将原本在结构中的某个key移除。

      getRandom():等概率随机返回结构中的任何一个key。

【要求】Insert、delete和getRandom方法的时间复杂度都是O(1)。

  package com.se.algorithm;

  import java.util.HashMap;
public class Code_RandomPool {
public static class Pool<K> {
private HashMap<K, Integer> keyIndexMap;
private HashMap<Integer, K> indexKeyMap;
private int size;
       //设置2个map,后一个map集合的键值对是前一个集合的键值对的互换
public Pool() {
this.keyIndexMap = new HashMap<K, Integer>();
this.indexKeyMap = new HashMap<Integer, K>();
this.size = 0;
}

public void insert(K key) {
if (!this.keyIndexMap.containsKey(key)) {
this.keyIndexMap.put(key, this.size);
this.indexKeyMap.put(this.size++, key);
}
}

public void delete(K key) {
if (this.keyIndexMap.containsKey(key)) {
int deleteIndex = this.keyIndexMap.get(key);
int lastIndex = --this.size;
K lastKey = this.indexKeyMap.get(lastIndex);
this.keyIndexMap.put(lastKey, deleteIndex);
this.indexKeyMap.put(deleteIndex, lastKey);
this.keyIndexMap.remove(key);
this.indexKeyMap.remove(lastIndex);
}
}

public K getRandom() {
if (this.size == 0) {
return null;
}
int randomIndex = (int) (Math.random() * this.size);
return this.indexKeyMap.get(randomIndex);
}

}

public static void main(String[] args) {
Pool<String> pool = new Pool<String>();
pool.insert("wan");
pool.insert("ling");
pool.insert("feng");
System.out.println(pool.getRandom());
System.out.println(pool.getRandom());

}

}




 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值