JavaScript解决哈希表冲突

Hash的基本实现

定义Hash类

function Hash() {
	this.hash = new Array(128)
	this.simpleHash = function(key) {
		// key为字符串
		let total = 0
		for(let i = 0;i < key.length;i++) {
			total += key.charCodeAt(i) * 10086
		}
		return total % this.hash.length
	}
	this.put = function(key, value) {
		let pos = this.simpleHash(key)
		this.hash[pos] = value
	}
	this.show = function() {
		for(let i = 0;i < this.hash.length;i++) {
			this.hash[i] ? console.log(`${i}: `, this.hash[i]) : ''
		}
	}
}

不同键值可能得到相同的hash值,如下:

let myHash = new Hash()
myHash.put('bc','I am curry')
myHash.put('I am the key...','I am the bucket...')
// 产生hash碰撞
myHash.put('ad','I am kyrie')
myHash.show()

哈希碰撞解决方法

开链法

每个对应Hash值的Hash Bucket对应一个链表(此处用二维数组模拟),链表中存储着键值对应的JSON数据,从而获取不同key时相同hash值情况下的bucket

function Hash1() {
	this.hash = new Array(128)
	for(let i = 0;i < this.hash.length;i++) {
		this.hash[i] = []
	}
	this.simpleHash = function(key) {
		// key为字符串
		let total = 0
		for(let i = 0;i < key.length;i++) {
			total += key.charCodeAt(i) * 10086
		}
		return total % this.hash.length
	}
	// hash值相同则加入该hash值的链表中
	this.put = function(key, value) {
		let index = 0
		let pos = this.simpleHash(key)
		if(!this.hash[pos][index]) {
			let jsonStr = `{"${key}" : "${value}"}`
			this.hash[pos][index] = JSON.parse(jsonStr)
		} else {
			index++
			while(this.hash[pos][index]) {
				index++
			}
			let jsonStr = `{"${key}" : "${value}"}`
			this.hash[pos][index] = JSON.parse(jsonStr)
		}
	}
	this.get = function(key) {
		let pos = this.simpleHash(key)
		let index = 0
		// 判断是否存在hash bucket
		if(typeof this.hash[pos][index] === 'object') {
			// 获取相同hash值的不同key值对应的bucket
			if(this.hash[pos][index][key]) {
				return this.hash[pos][index][key]
			} else {
				while(typeof this.hash[pos][index] === 'object') {
					if(this.hash[pos][index][key]) {
						break
					}
					index++
				}
				return this.hash[pos][index][key]
			}
		} else {
			return "this key isn't exist"
		}
	}
}

调试

let myHash1 = new Hash1()
myHash1.put('bc','I am curry')
myHash1.put('I am the key...','I am the bucket...')
// 产生hash碰撞
// hash值都为126
myHash1.put('ad','I am kyrie')
console.log(myHash1.hash[126]) //[ { bc: 'I am curry' }, { ad: 'I am kyrie' } ]
console.log('开链法:', myHash1.get('ad')) //开链法: I am kyrie

线性探测

开发寻址散列,若发生hash碰撞,则当前key的hash值自增向下寻找空值的索引.

function Hash2() {
	// hash存储唯一键值
	// bucket存取键值对应的bucket
	this.hash = new Array(128)
	this.bucket = new Array(128)
	this.simpleHash = function(key) {
		// key为字符串
		let total = 0
		for(let i = 0;i < key.length;i++) {
			total += key.charCodeAt(i) * 10086
		}
		return total % this.hash.length
	}
	this.put = function(key, value) {
		let pos = this.simpleHash(key)
		if(!this.hash[pos]) {
			// 存储唯一键值
			this.hash[pos] = key
			// 存取bucket
			this.bucket[pos] = value
		} else {
			while(this.hash[pos]) {
				if(pos < this.hash.length) {
					pos++
				}
				else {
					console.error('full..')
					return
				}
			}
			this.hash[pos] = key
			this.bucket[pos] = value
		}
	}
	this.get = function(key) {
		let pos = this.simpleHash(key)
		while(this.hash[pos]) {
			if(this.hash[pos] === key) {
				return this.bucket[pos]
			}
			pos++
		}
		return 'not exist'
	}
}

调试:

let myHash2 = new Hash2()
myHash2.put('bc','I am curry')
myHash2.put('I am the key...','I am the bucket...')
// 产生hash碰撞
// hash值都为126
myHash2.put('ad','I am kyrie')
console.log('线性探测:',myHash2.get('ad')) // 线性探测: I am kyrie

猜你喜欢

转载自blog.csdn.net/kyr1e/article/details/83099307