JavaScript——哈希表(链地址法)

JavaScript——哈希表(链地址法)

/*哈希表类(链地址法)
哈希表里每个索引对应的元素为一个桶(bucket),每个桶为一个数组。
桶里的每个元素也是一个数组,称为元组(tuple)
每个元组由key和value组成
哈希表整体结构:[[[key,value],[key,value],...],[[key,value],[key,value],...],...]
*/
function HashTable(){
	this.storage = []
	//当前元素个数
	this.count = 0
	//哈希表长度(质数)
	this.limit = 7
	/*
	* 哈希函数,返回字符串对应的索引
	* 参数1:key , 参数2:哈希表的长度
	*/ 
	HashTable.prototype.hashFunc = function(key, size){
		let hashCode = 0
		key = String(key)
		//霍纳算法,计算hashCode的值
		for (let i =0; i < key.length; i++){
			hashCode = 37 * hashCode + key.charCodeAt(i)
		}
		//求余,返回小于哈希表长度的索引
		let index = hashCode % size
		return index
	}
	/*
	* 1.插入或修改数据
	*/ 
	HashTable.prototype.put = function(key, value){
		let index = this.hashFunc(key, this.limit)
		//取出对应索引的元素(桶)
		let bucket = this.storage[index]
		//1. 桶不为空的情况
		if (bucket){
			//寻找对应的key是否已经存在
			for (let i = 0; i < bucket.length; i++){
				let tuple = bucket[i]
				//对应key已存在则将原value覆盖
				if (tuple[0] == key){
					tuple[1] = value
					return
				}
			}
			//对应key不存在则往桶里添加一条新数据
			bucket.push([key, value])
		}
		//2. 桶为空的情况
		else{
			//创建一个新的桶
			bucket = []
			this.storage[index] = bucket
			bucket.push([key, value])
		}
		//元素个数+1
		this.count += 1
		//判断哈希表是否需要扩容(当前元素个数大于总长度的0.75时需要扩容,否则操作效率会变低)
		if (this.count > this.limit * 0.75){
			let newLimit = this.getPrime(this.limit * 2)
			this.resize(newLimit)
		}
	}
	/*
	* 2.查找数据
	*/ 
	HashTable.prototype.get = function(key){
		let index = this.hashFunc(key, this.limit)
		let bucket = this.storage[index]
		//桶不为空
		if (bucket){
			for (let i =0; i < bucket.length; i++){
				let tuple = bucket[i]
				if (tuple[0] == key){
					return tuple[1]
				}
			}
		}
		//桶为空或遍历完都没查找到
		return null
	}
	/*
	* 3. 删除数据
	*/ 
	HashTable.prototype.remove = function(key){
		let index = this.hashFunc(key, this.limit)
		let bucket = this.storage[index]
		//桶不为空
		if (bucket){
			for (let i = 0; i < bucket.length; i++){
				let tuple = bucket[i]
				if (tuple[0] == key){
					//删除数据,哈希表元素个数-1
					bucket.splice(i, 1)
					this.count -= 1
					//判断哈希表是否需要缩容(当前元素个数小于总长度的0.25时需要缩容,但长度不能小于7)
					if (this.limit > 7 && (this.count < this.limit * 0.25)){
						let newLimit = this.getPrime(parseInt(this.limit / 2))
						this.resize(newLimit)
					}
					//返回删除的数据
					return tuple[1]
				}
			}
		}
		//桶为空或遍历完都没查找到要删除的数据
		return null
	}
	/*
	* 4.质数判断
	*/
	HashTable.prototype.isPrime = function(num){
		let sqrtNum = parseInt(Math.sqrt(num))
		for (let i = 2; i <= sqrtNum; i++){
			if (num % i == 0){
				return false
			}
		}
		return true
	}
	/*
	* 5.获取质数
	*/ 
	HashTable.prototype.getPrime = function(num){
		while (this.isPrime(num) == false){
			num += 1
		}
		return num
	}
	/*
	* 6. 哈希表扩容或缩容
	*/
	HashTable.prototype.resize = function(newLimit){
		//保存原哈希表数据
		let oldStorage = this.storage
		//清空原哈希表数据
		this.storage = []
		this.count = 0
		this.limit = newLimit
		//遍历得到所有桶
		for (let i =0; i < oldStorage.length; i++){
			let bucket = oldStorage[i]
			//判断桶里否有数据
			if (bucket){
				//将桶里的所有数据(元组)重新添加到新哈希表
				for (let y = 0; y < bucket.length; y++){
					let tuple = bucket[y]
					this.put(tuple[0], tuple[1])
				}
			}
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值