export function hashFn(string, limit = 7) { const PRIME = 31 let hashCode = 0 for (let item of string) { hashCode = PRIME * hashCode + item.charCodeAt() } return hashCode % limit } export function isPrime(number) { if (number <= 1) return false let temp = Math.ceil(Math.sqrt(number)) for (let i = 2; i < temp; i++) { if (number % i === 0) { return false } } return true } export class HashTable { constructor() { this.storage = [] this.count = 0 //åå¨å½ååæ¾å ç´ çä¸ªæ° this.limit = 7 // åå¸è¡¨çé¿åº¦ // å¡«å å åï¼å·²æä¸ªæ°/æ»ä¸ªæ° this.loadFactor = 0.75 this.minLoadFactor = 0.25 } //æ ¹æ®numberè·åæä¸´è¿çè´¨æ° getPrime(number) { while (!isPrime(number)) { number++ } return number } // å¾hash é颿·»å æ°æ®(å设æ¯ä¸ä¸ªä¸ä½æ°ç») // é¦å æ¾å°åºè¯¥æ·»å å°çä¸ç»´çä¸è¡¨ï¼ç¶åæ¾å°äºä½æ°ç»çå°æ¹ï¼æå卿·»å put(key, value) { let index = this.storage[this.hashFn(key)] //1ãæ ¹æ® key è·åè¦æ å°å° storage éé¢ç indexï¼éè¿åå¸å½æ°è·åï¼ let bucket = this.storage[index] // 2ãæ ¹æ® index ååºå¯¹åºç bucket if (bucket === undefined) { //3ã夿æ¯å¦åå¨ bucket bucket = [] this.storage[index] = bucket } // 4ãå¤ææ¯æå ¥æ°æ®æä½è¿æ¯ä¿®æ¹æ°æ®æä½ for (let i = 0; i < bucket.length; i++) { let tuple = bucket[i] if (tuple[0] === key) { // 妿 key ç¸çï¼åä¿®æ¹æ°æ® tuple[1] === value // ä¿®æ¹å® tuple éæ°æ®ï¼return ç»æ¢ï¼ä¸åå¾ä¸æ§è¡ã return } } // 5ãbucket æ°å¢æ°æ® this.bucket.push([key, value]) this.count++ // 夿åå¸è¡¨æ¯å¦è¦æ©å®¹ï¼è¥è£ å¡«å å > 0.75ï¼åæ©å®¹ if (this.count / this.limit > this.loadFactor) { this.resize(this.getPrime(this.limit * 2)) } } // æ ¹æ® get(key) è·å value get(key) { let index = this.storage[this.hashFn(key)] //1ãæ ¹æ® key è·åè¦æ å°å° storage éé¢ç indexï¼éè¿åå¸å½æ°è·åï¼ let bucket = this.storage[index] // 2ãæ ¹æ® index ååºå¯¹åºç bucket if (bucket === undefined) { //3ã夿æ¯å¦åå¨ bucket return null } // 4ãå¤ææ¯æå ¥æ°æ®æä½è¿æ¯ä¿®æ¹æ°æ®æä½ for (let i = 0; i < bucket.length; i++) { let tuple = bucket[i] if (tuple[0] === key) { // 妿 key ç¸çï¼åä¿®æ¹æ°æ® return tuple[1] } } return null } // remove(key) å é¤æå® key çæ°æ® remove(key) { let index = this.storage[this.hashFn(key)] //1ãæ ¹æ® key è·åè¦æ å°å° storage éé¢ç indexï¼éè¿åå¸å½æ°è·åï¼ let bucket = this.storage[index] // 2ãæ ¹æ® index ååºå¯¹åºç bucket if (bucket === undefined) { //3ã夿æ¯å¦åå¨ bucket return null } // 4ãå¤ææ¯æå ¥æ°æ®æä½è¿æ¯ä¿®æ¹æ°æ®æä½ for (let i = 0; i < bucket.length; i++) { let tuple = bucket[i] if (tuple[0] === key) { // 妿 key ç¸çï¼åä¿®æ¹æ°æ® bucket.splice(i, 1) this.count--; // æ ¹æ®è£ å¡«å åç大å°ï¼å¤ææ¯å¦è¦è¿è¡åå¸è¡¨å缩 if (this.limit > 7 && this.count / this.limit < this.minLoadFactor) { this.resize(this.getPrime(Math.floor(this.limit / 2))); } return tuple } } return null } isEmpty() { return this.count === 0 } size() { return this.count } // éæ°è°æ´åå¸è¡¨å¤§å°ï¼æ©å®¹æå缩 resize(newLimit) { const oldStorage = this.storage this.storage = [] this.count = 0 this.limit = newLimit // 3ãéå oldStorageï¼ååºæææ°æ®ï¼éæ° put å° this.storage for (let bucket of oldStorage) { if (bucket) { for (const b of bucket) { this.put(b[0], b[1]) } } } } }