哈希表:基於數組,不能重複且無序
將名稱及單詞與下標或數字對應起來
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>