第十四章 哈希表

14-1 哈希表基础

知识点:
1 将 a-z 字幕的 ascii 码出现次数映射到 0-25 的数组中 , 哈希函数 f(char)=char-'a' O(1) , 键转换为索引
2 26 个字幕和 1-30 学号这样的哈希函数很容易能找到一一对应的索引 , 但是身份证,字符串,浮点数,日期却不能 , 可能是多对一 , 因而产生哈希冲突
3 哈希表的设计思想: 空间换时间 , 假如1101819851216666 的身份证 , 可以开辟无限大的 99999999999999 的数组,则可以用 O(1)的时间执行任意操作 , 假如只有 1 的空间, 则只能类似链表(线性表) , O(n)的时间操作

func firstUniqChar(s string) int {
    /*
    make a arr , map 0-25 as a-z
     */
    arr:=[26]int{}

    for _,v:=range s {
            arr[v-'a']++

    }

    for k,v:=range s {
        if arr[v-'a']==1 {
            return k
        }
    }
    return -1

}

14-2 哈希函数设计

知识点
1 哈希函数 得到的索引 分布越均匀越好
所有类型都转换为整形的哈希函数设计:
2小范围正整数直接用 , 负整数做偏移 -100~100 -> 0~200

3大整数的哈希函数:取模 , 身份证号取后四位 = mod 10000 12343253255312056666 -> 6666 ,
4 mod1000000->056666 , 1205 是生日 , 05 部分取值为01~31 , 而哈希空间为 00~99 , 造成了分布不均匀
5 每个领域都有不同的哈希函数设计 , 很难找到通用的设计
6 对身份证号取模没有利用所有信息( 信息摘要的概念? ) , 因此更容易产生冲突 , 信息越多越能接近唯一性 , 如用年月日区分 , 对比用省市区+年月日 , 更容易产生重复
7 模一个素数 , 更有效利用一个数字的所有信息 , 数论


图片

图片

8 32浮点型在计算机中的表示 , 32 或 64 位的二进制数 , 32 位的情况,单精度 从左边起 , 第一位是符号位 , 2-9 共 8 位是 exponent , 指数位 , 后面 23 位是 fraction 小数位
9 64 位浮点型的表示 , 第一符号位 , 2-12 , 11 位指数位 , 后面是 52 位的小数位
10 浮点型直接当做整形 , 然后同上作哈希
11 字符串也转成整型
12 166 也可以看成字符串 110^2 + 610^1 + 610^0
13 英文字母可以看成 26 进制 , code=c
26^4 + o*26^3 ...........
14 字符串特别长的时候可能计算很慢 , 可以做变形减少计算次数

14-2 哈希函数设计

15 字符串特别长并且使用的进制特别大的时候可能产生溢出 , 可以把取模移到每一个里面

14-2 哈希函数设计

16 字符串哈希函数解决方案

14-2 哈希函数设计

17 复合类型 , 如类 , 将类中的属性 , 如 Date { year,month,day} , 取出来同上面的字符串一样取哈希

18 并不一定需要转成整型处理 , 还有其他方法

19 哈希函数设计原则 , 一致性 a 的哈希值永远是同一个 , 高效性, 计算速度快 , 均匀 , 分布均匀

14-3 链地址法

知识点
1 取绝对值 和0x7ffffffff 进行与操作 , 7 个 f = 7*4=28个 1 , 7 表示为 0111 ,
0111 ....11111 , 符号位取 0 为正数

14-2 链地址法 Seperate Chaining

2 元素为查找表 , 如链表 , 平衡树 (PHP 的为链表,头插法 , Java 里有一个HashMap是红黑树的实现)

3 如何用 map 实现 set ? 如何复用 hashmap 实现 hashset , 用 map 的 key 存储 set 的 value
4 HashSet HashMap 的区别?
5 数据量小链表比较快 , 大则红黑树比较快


14-2 链地址法 Seperate Chaining

你可能感兴趣的:(第十四章 哈希表)