哈希表——js實現哈希表

哈希表:基於數組,不能重複且無序

將名稱及單詞與下標或數字對應起來

1.將字母或單詞轉換成下標或數字(hashCode)——過程講解:

方案一:數字相加——數組下標太小

方案二:冪的連乘——數組下標太多

方案改進:哈希化,例如取餘操作

     

衝突:哈希化後依然有數組下標會重複

解決衝突的兩種方案:1.鏈地址法(拉鍊法)2.開放地址法

一:鏈地址法

將衝突(產生衝突的元素一般比較少)的元素放到一個鏈表(或數組)中,將該鏈表存儲於該數組下標位置處

二:開放地址法

尋找空白單元格來添加重複的數據(一般數組的空間會是實際數據需求空間的了兩倍)

解決衝突方法:1.線性探測 2.二次探測(修改探測步長) 3.再哈希化的哈希函數  :stepSize=constant-(key%constant)

快速計算:霍納法則

 

put插入數據函數的封裝

get方法圖解思路

刪除數據

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
			function HashTable(){
				this.storage = []
				this.count = 0
				this.limit = 7
				HashTable.prototype.hashFunc = function(str, size){
					//1.定義hashCode變量
					var hashCode = 0
					//2.根據霍納算法,計算hashCode的值
					//藉助Unicode編碼計算
					for(var i=0; i< str.length; i++){
						hashCode = 37 * hashCode + str.charCodeAt(i)
					}
					
					//3.取餘操作 5%4=1
					var  index = hashCode % size
					return index
				}
				
				HashTable.prototype.put = function(key, value){
					//1.根據key獲取對應的index
					var index = this.hashFunc(key,this.limit)
					
					//2.根據index取得對應的bucket(bucket是key的hashCode對應下表位置,)
					var bucket = this.storage[index]
					//3.判斷當前bucket是否爲空
					if(bucket == null){
						bucket = []
						this.storage[index] = bucket
					}
					
					//4.判斷是否修改數據
					for(var i= 0; i< bucket.length; i++){
						var tuple = bucket[i]
						if(tuple[0]==key){
							tuple[1] = value
							return
						}
					}
					
					//5.當前bucket(鏈表)中沒有該數據,就直接添加該數據
					bucket.push([key, value])
					this.count +=1
				}
				
				//get獲取元素
				HashTable.prototype.get = function(key){
					/**
					*1.根據key,獲得index;
					* 2.根據index,獲得bucket;
					* 3.判斷bucket是否爲null,爲null就直接返回null
					* 4.bucket不爲null,則遍歷找到對應的key
					* 5.遍歷完後,沒有找到對應的key,就返回null
					**/
					var index = this.hashFunc(key,this.limit)
					var bucket = this.storage[index]
					if(bucket == null){
						return null
					}
					for(var i=0;i< bucket.length;i++){
						var tuple = bucket[i]
						if(tuple[0]== key){
							return tuple[1]
						}
					}
					//在index對應的bucket(不爲null)中沒有找到對應的key
					return null
					
				}
				
				//remove方法
				HashTable.prototype.remove = function(key){
					var index = this.hashFunc(key,this.limit)
					var bucket = this.storage[index]
					if(bucket == null){
						return null
					}
					for(var i=0; i<bucket.length;i++){
						var tuple = bucket[i]
						if(tuple[0] == key){
							bucket.splice(i,1)//刪除當前位置的元素https://wangdoc.com/javascript/stdlib/array.html#splice
							this.count--
							return tuple[1]
						}
					}
					
					return null
				}
				
				HashTable.prototype.isEmpty = function(){
					return this.count==0
				}
				HashTable.prototype.size = function(){
					return this.count
				}
			}
			
			var ht = new HashTable()
			
			ht.put('abc','123')
			ht.put('abd','456')
			ht.put('cbd','789')
			ht.put('aee','235')
			
			alert(ht.get('abc'))
			
			ht.put('abc','111')
			alert(ht.get('abc'))
			
			ht.remove('abc')
			alert(ht.get('abc'))
			
			
		</script>
	</body>
</html>

實現容量恆爲質數

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script>
			function HashTable(){
				this.storage = []
				this.count = 0
				this.limit = 7
				HashTable.prototype.hashFunc = function(str, size){
					//1.定義hashCode變量
					var hashCode = 0
					//2.根據霍納算法,計算hashCode的值
					//藉助Unicode編碼計算
					for(var i=0; i< str.length; i++){
						hashCode = 37 * hashCode + str.charCodeAt(i)
					}
					
					//3.取餘操作 5%4=1
					var  index = hashCode % size
					return index
				}
				
				HashTable.prototype.put = function(key, value){
					//1.根據key獲取對應的index
					var index = this.hashFunc(key,this.limit)
					
					//2.根據index取得對應的bucket(bucket是key的hashCode對應下表位置,)
					var bucket = this.storage[index]
					//3.判斷當前bucket是否爲空
					if(bucket == null){
						bucket = []
						this.storage[index] = bucket
					}
					
					//4.判斷是否修改數據
					for(var i= 0; i< bucket.length; i++){
						var tuple = bucket[i]
						if(tuple[0]==key){
							tuple[1] = value
							return
						}
					}
					
					//5.當前bucket(鏈表)中沒有該數據,就直接添加該數據
					bucket.push([key, value])
					this.count +=1
					
					//數組擴容
					if(this.count > this.limit * 0.75 ){
						var newSize = this.limit * 2
						var newPrime = this.getPrime(newSize)
						this.resize(newPrime)
					}
				}
				
				//get獲取元素
				HashTable.prototype.get = function(key){
					/**
					*1.根據key,獲得index;
					* 2.根據index,獲得bucket;
					* 3.判斷bucket是否爲null,爲null就直接返回null
					* 4.bucket不爲null,則遍歷找到對應的key
					* 5.遍歷完後,沒有找到對應的key,就返回null
					**/
					var index = this.hashFunc(key,this.limit)
					var bucket = this.storage[index]
					if(bucket == null){
						return null
					}
					for(var i=0;i< bucket.length;i++){
						var tuple = bucket[i]
						if(tuple[0]== key){
							return tuple[1]
						}
					}
					//在index對應的bucket(不爲null)中沒有找到對應的key
					return null
					
				}
				
				//remove方法
				HashTable.prototype.remove = function(key){
					var index = this.hashFunc(key,this.limit)
					var bucket = this.storage[index]
					if(bucket == null){
						return null
					}
					for(var i=0; i<bucket.length;i++){
						var tuple = bucket[i]
						if(tuple[0] == key){
							bucket.splice(i,1)//刪除當前位置的元素https://wangdoc.com/javascript/stdlib/array.html#splice
							this.count--
							return tuple[1]
							
							//縮小容量
							if(this.limit>7 && this.count < this.limit * 0.25){
								var newSize = Math.floor(this.limit / 2)
								var newPrime = this.getPrime(newSize)
								this.resize(newPrime)
							}
						}
					}
					
					return null
				}
				
				HashTable.prototype.isEmpty = function(){
					return this.count==0
				}
				HashTable.prototype.size = function(){
					return this.count
				}
				
				//哈希表的擴容
				HashTable.prototype.resize = function(newLimit){
					var oldStorage = this.storage
					
					this.storage = []
					this.count =0
					this.limit = newLimit
					
					var bucket = []
					for(var i=0;i<this.count;i++){
						bucket = oldStorage[i]
						if(bucket == null){
							continue
						}
						for(var j=0; j<bucket.length;j++){
							var tuple =bucket[i]
							this.put(tuple[0],tuple[1])
						}
					}
				}
				
				//判斷數字是否是質數
				HashTable.prototype.isPrime = function (num){
					//1.獲得num的平方根
					var temp = parseInt(Math.sqrt(num))
					
					for(var i =2; i< temp; i++){
						if(num % i == 0){
							return false
						}
					}
					
					return true
				}
				
				//獲取質數的方法
				HashTable.prototype.getPrime = function(num){
					while(!this.isPrime(num)){
						num++
					}
					return num
				}
				
			}
			
			var ht = new HashTable()
			
			ht.put('abc','123')
			ht.put('abd','456')
			ht.put('cbd','789')
			ht.put('aee','235')
			
			alert(ht.get('abc'))
			
			ht.put('abc','111')
			alert(ht.get('abc'))
			
			ht.remove('abc')
			alert(ht.get('abc'))
			
			
		</script>
	</body>
</html>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章