概念和用途

  • 散列后的数据可以快速插入取用
  • 在散列表上插入、删除和取用数据非常快,但是查找数据却效率低下,比如查找一组数据中的最大值和最小值
  • ◆JavaScript散列表基于数组设计,理想情况散列函数会将每一个键值映射为唯的数组索引,数组长度有限制,更现实的策略是将键均匀分布。

关键定义

  • 两个键值相同的情况,这种现象称为碰撞
  • 数组长度应该是一个质数,所有策略都基于碰撞
  • 开链法:两个键相同保存位置一样,开辟第二数组,也称第二个数组为链
  • 线性探测法属于开放寻址散列,查找散列位置如果当前位置没有继续寻找下一个位置。
  • 存储数据较大较合适。数组大小》=1.5数据,使用开链法,数组大小》=2数据,使用线性探测法。

代码实现

  1. function hashTable() {
  2. // 1. 给质数长度的数组,为了防碰撞
  3. this.table = new Array(159)
  4. // 2.1 获取hash
  5. this.simpleHash = simpleHash
  6. // 2.2 展示hash
  7. this.display = display
  8. // 2.3 增
  9. this.put = put
  10. // 2.4 查
  11. this.get = get
  12. // 3.1 解决碰撞1:betterHash
  13. this.betterHash = betterHash
  14. // 3.2 解决碰撞2:开链法——创造一个数组,存在了就push进去
  15. this.buildChain = buildChain
  16. // 3.3 解决碰撞3:线性探测法——如果碰撞了,则一直往下找到没有碰撞的位置(如果找到最后都没有位置呢?插入失败?)
  17. }
  18. function buildChain () {
  19. for (let index = 0; index < this.table.length; index++) {
  20. this.table[index] = []
  21. }
  22. }
  23. function simpleHash(ele) {
  24. var total = 0;
  25. for (let index = 0; index < ele.length; index++) {
  26. // string.charCodeAt(i) string.charAt(i)
  27. // 'abc'.charCodeAt(1) == 98 'abc'.charAt(1) == b
  28. total += ele.charCodeAt(index)
  29. }
  30. // 就这么记吧,我也不知道为啥,哎
  31. // console.log('simpleHash res is :', total % 137)
  32. return total % 137
  33. }
  34. function betterHash(ele) {
  35. // 放大算法,在total上乘上个质数 让结果更均匀一些
  36. const GG = 99
  37. var total = 0;
  38. for (let index = 0; index < ele.length; index++) {
  39. total += total * GG + ele.charCodeAt(index)
  40. }
  41. console.log('simpleHash res is :', total % 137)
  42. return total % 137
  43. }
  44. function display() {
  45. for (let index = 0; index < this.table.length; index++) {
  46. if (this.table[index]) {
  47. console.log(`index: ${index}, value: ${this.table[index]}`)
  48. }
  49. // 开链法改造:
  50. // if (this.table[index][0]) {
  51. // console.log(`index: ${index}, value: ${this.table[index]}`)
  52. // }
  53. }
  54. }
  55. function put(ele) {
  56. var pos = this.simpleHash(ele)
  57. // this.table[pos] = ele
  58. // 线性探测法判断空位
  59. if (!this.table[pos]) {
  60. this.table[pos] = ele
  61. } else {
  62. while(this.table[pos] != undefined) {
  63. pos++
  64. }
  65. this.table[pos] = ele
  66. }
  67. // 开链法改造:
  68. // var index = 0
  69. // if (!this.table[pos][index]) {
  70. // this.table[pos][index] = ele
  71. // } else {
  72. // while(this.table[pos][index] != undefined) {
  73. // index++
  74. // }
  75. // this.table[pos][index] = ele
  76. // }
  77. }
  78. function get(ele) {
  79. // 第一次实现是下面这个东西,看起来很蠢
  80. // return this.table[key]
  81. // 课程实现的是下面这东西,看起来很厉害的蠢
  82. // return this.table[this.simpleHash(ele)]
  83. // 线性探测法,来获取原本的index和最终的index
  84. var hash = this.simpleHash(ele)
  85. // 从hash开始是因为碰撞是从 hash开始的
  86. console.log('原始hash: ', hash)
  87. for (let index = hash; index < this.table.length; index++) {
  88. if (this.table[index] == ele) {
  89. return index
  90. }
  91. }
  92. return false
  93. }
  94. var hashT = new hashTable()
  95. // hashT.buildChain()
  96. hashT.put('china')
  97. hashT.put('japan')
  98. hashT.put('america')
  99. // 与china产生了碰撞,接下来改进hash算法
  100. hashT.put('incha')
  101. hashT.put('incha')
  102. hashT.put('incha')
  103. hashT.put('incha')
  104. hashT.put('incha')
  105. hashT.put('incha')
  106. hashT.put('incha')
  107. hashT.put('incha')
  108. hashT.put('incha')
  109. hashT.put('incha')
  110. hashT.put('incha')
  111. hashT.put('incha')
  112. hashT.put('incha')
  113. hashT.put('incha')
  114. hashT.put('incha')
  115. hashT.put('incha')
  116. hashT.put('incha')
  117. hashT.put('incha')
  118. hashT.put('incha')
  119. hashT.put('incha')
  120. hashT.put('incha')
  121. hashT.put('incha')
  122. hashT.put('incha')
  123. hashT.put('incha')
  124. hashT.put('incha')
  125. hashT.put('incha')
  126. hashT.put('incha')
  127. hashT.put('incha')
  128. hashT.put('incha')
  129. hashT.put('incha')
  130. hashT.put('incha')
  131. hashT.put('incha')
  132. hashT.put('incha')
  133. hashT.put('incha')
  134. hashT.put('incha')
  135. hashT.put('incha')
  136. hashT.put('incha')
  137. hashT.put('incha')
  138. hashT.put('incha')
  139. hashT.put('incha')
  140. hashT.put('incha')
  141. hashT.put('incha')
  142. hashT.put('incha')
  143. hashT.put('incha')
  144. hashT.put('incha')
  145. hashT.put('incha')
  146. hashT.put('incha')
  147. hashT.put('incha')
  148. hashT.put('incha')
  149. hashT.put('incha')
  150. hashT.put('incha')
  151. hashT.put('incha')
  152. hashT.put('incha')
  153. hashT.put('incha')
  154. hashT.put('incha')
  155. hashT.put('incha')
  156. hashT.put('incha')
  157. hashT.put('incha')
  158. hashT.put('incha')
  159. hashT.put('incha')
  160. hashT.put('incha')
  161. hashT.put('incha')
  162. hashT.put('incha')
  163. hashT.put('incha')
  164. hashT.put('incha')
  165. hashT.put('incha')
  166. hashT.put('incha')
  167. hashT.put('incha')
  168. hashT.put('incha')
  169. hashT.put('incha')
  170. hashT.put('incha')
  171. hashT.put('incha')
  172. hashT.put('incha')
  173. hashT.put('incha')
  174. hashT.put('incha')
  175. hashT.put('incha')
  176. hashT.put('incha')
  177. hashT.put('incha')
  178. hashT.put('incha')
  179. hashT.put('incha')
  180. hashT.put('incha')
  181. hashT.put('incha')
  182. hashT.put('incha')
  183. hashT.put('incha')
  184. hashT.put('incha')
  185. hashT.put('incha')
  186. hashT.put('incha')
  187. hashT.put('incha')
  188. hashT.put('incha')
  189. hashT.put('incha')
  190. hashT.put('incha')
  191. hashT.put('incha')
  192. hashT.put('incha')
  193. hashT.put('incha')
  194. hashT.put('incha')
  195. hashT.put('incha')
  196. hashT.put('incha')
  197. hashT.put('incha')
  198. hashT.put('incha')
  199. console.log('length:', hashT.table.length, '------------------------')
  200. // 所以就溢出了呗,这个后面有用到这玩意再说吧,先了解着
  201. hashT.display()
  202. console.warn(hashT.get('incha'))