day15 如何通过哈希查找JS对象内存地址?

散列表:
素数哈希、ASCII 哈希,还有 djb2
素数哈希:把一个素数作为模数(modulus number)
来给你举一个例子,在这个例子里,我们把 11 这个素数作为了模数,用下面的一组键值对中的键除以模数,所获得的余数,放到一个数组中。就形成了一个散列表。

{key:7, value: "南昌"}
{key:24, value: "太原"}
{key:42, value: "郑州"}
Prime number: 11
7 % 11  = 7 // 余数为7
24 % 11 = 2 // 余数为2
42 % 11 = 9 // 余数为9

存在的问题:如果处理的数据数量足够多,那么就会出现冲突的情况。
为了尽量减少这种冲突,业界也在尝试其他办法,比如使用 ASCII code 和素数结合来生成哈希,但这种方式和上面的素数哈希一样,即使结合了 ASCII,哈希值也不能完全避免碰撞的产生,只能减少冲突。

asciiHashCode(key) {
  if (typeof key === 'number') { 
    return key;
  }
  const tableKey = this.toStrFn(key); 
  let hash = 0; 
  for (let i = 0; i < tableKey.length; i++) {
    hash += tableKey.charCodeAt(i); 
  }
  return hash % 37; 
}

djb2 的算法:
先用一个长质数 5381 作为哈希数,然后根据字符串长度循环,将哈希数乘以 33,再加上字符的 ASCII 码迭代。结果和模数 1013 的余数结果就是最后的哈希值。

djb2HashCode(key) {
  const tableKey = this.toStrFn(key); 
  let hash = 5381; 
  for (let i = 0; i < tableKey.length; i++) { 
    hash = (hash * 33) + tableKey.charCodeAt(i); 
  }
  return hash % 1013; 
} 

字典:如何查找对象的内存地址
散列表可以只有值,没有键,可以说是数组延伸出来的索引。
通常字典是有键值对的。字典作为一种数据结构,又叫做映射(map)、符号表(symbol table)或者关联数组(associative array)。
在 JavaScript 中,我们其实可以把对象看做是一种可以用来构建字典的一种散列表,因为对象里就包含 key-value 的属性。
对象在栈的引用和它在堆中的实际存储间的关联就是通过地址映射来实现的。这种映射关系就是通过字典来存储的。
Map 和 Set:各解决什么问题
JavaScript 中的 Map 就是字典的结构,它里面包含的就是键值对。 我们说过对象就是一个可以用来实现字典的支持键值对的散列表。Map 和对象最大的区别就是 Map 里的键可以是字符串以外的其它数据结构,比如对象也可以是一个键名。
JavaScript 中的 Set 就是集合的结构,它里面包含值,没有键。与数组的区别主要在于 JS 中的集合属于无序集合,并且里面不能有相同的元素。
WeakMap 或 WeakSet
第一,它们都是弱类型,代表没有键的强引用。所以 JavaScript 在垃圾回收时可以清理掉整条记录。第二个原因,也是它的特点,在于既然 WeakMap 里没有键值的迭代,只能通过钥匙才能取到相关的值,所以保证了内部的封装私有属性。
散列冲突:解决哈希碰撞的方式
线性探查法、平方探测法和二度哈希法。
线性探查法
当一个散列碰撞发生时,程序会继续往下去找下一个空位置,比如在之前例子中,7 被南昌占用了,北京就会顺移到 8。

day15 如何通过哈希查找JS对象内存地址?_第1张图片
平方探测法
平方探测法用平方值来代替线性探查法中的往后顺移一位的方式,这样就可以做到基于有效的指数做更平均的分布。
图片
二度哈希法
第一次的哈希的基础上再次哈希。在下面公式里,x 是第一次哈希的结果,R 小于哈希表。假设每次迭代序列号是 i,每次哈希碰撞通过 i * hash2(x) 来解决。
hash2(x) = R − (x % R)
day15 如何通过哈希查找JS对象内存地址?_第2张图片
HashMap:Java 是如何解决散列冲突的?
HashMap、LinkedHashMap 和 TreeMap。
HashMap:底层逻辑是通过链表和红黑树实现的。
规则是,当哈希函数生成的哈希值有冲突的时候,就把有冲突的数据放到一个链表中,以此来解决哈希碰撞。当冲突的数据过多的时候,它就会产生性能上的问题,这个时候用增删改查的红黑树来代替会更合适。
day15 如何通过哈希查找JS对象内存地址?_第3张图片
散列加链表:基于双链表存值排序
LinkedHashMap:是在 HashMap 的基础上,内部维持了一个双向链表(Doubly Linked List),它利用了双向链表的性能特点,可以起到另外一个非常重要的作用,就是可以保持插入的数据元素的顺序。
day15 如何通过哈希查找JS对象内存地址?_第4张图片
TreeMap:基于红黑树的键值排序

TreeMap 也是 Java 一种基于红黑树实现的字典,但是它和 HashMap 有着本质的不同,它完全不是基于散列表的。而是基于红黑树来实现的。相比 HashMap 的无序和 LinkedHashMap 的存值有序,TreeMap 实现的是键值有序。它的查询效率不如 HashMap 和 LinkedHashMap,但是相比前两者,它是线程安全的。

day15 如何通过哈希查找JS对象内存地址?_第5张图片

你可能感兴趣的:(前端javascript)