散列算法的作用是尽可能快地在数据结构中找到一个值。如果数据很大,但是有需要遍历整个数据结构来查找到该值,花费的时间就太多了。所以散列表在查找方面中比较优势:使用散列函数,就知道具体位置,能够快速检索。散列函数的作用:给定一个key值,返回key值在表中的地址。
1 function HashTable(){ 2 //初始化散列表 3 var table=[]; 4 //散列函数(私有方法) 5 var loseloseHashCode = function(key){ 6 var hash=0; 7 for(var i=0;i<key.length;i++){ 8 hash += key.charCodeAt(i); 9 } 10 //因为相加的hash值很大,为了得到较小的数值,hash值与任意一个数取余 11 return hash%37; 12 }; 13 14 //最被社区推荐的散列函数 15 var djb2HashCode = function(key){ 16 //初始化hash变量,并且赋值为一个质数,大多数使用5381 17 //将hash与33(魔力数)相乘 18 var hash=5381; 19 for(var i=0;i<key.length;i++){ 20 hash=hash*33+key.charCodeAt(i); 21 } 22 //相加后的hash值最后一个质数相除取余,这个质数要逼散列表的大小要大一点。 23 return hash%1013; 24 }; 25 //把值放入哈希表中 26 this.put = function(key,value){ 27 var position=loseloseHashCode(key); 28 //console.log可有可无 29 console.log(position+"-"+key); 30 table[position]=value; 31 }; 32 //获取 33 this.get = function(key){ 34 return table[loseloseHashCode(key)]; 35 }; 36 //移除 37 this.remove=function(key){ 38 table[loseloseHashCode(key)]=undefined; 39 } 40 }
上述HashTable函数中,有一个很明显的缺点就是如果插入的不同key但是ASCII值相同情况下,会发生覆盖。后面存入的值会覆盖前面存入的值。为了解决冲突,可以使用分离链接,线性探查和双散列法。
分离链接法,在散列表的每个位置创建一个链表并将元素存储在里面。简单一点来说就是在,每个位置上,再建立一个链表,一次存放不同的key值。这种方法因为有链表,所以会增加额外的存储空间。
线性探查法。假设想在[320]位置上放入一个新的元素。如果[320]位置上为空,没有元素存储,则直接放入;如果有元素占据了该位置,则尝试[320+1]位置,即是下一个位置,如果[320+1]的位置被占据了,则尝试[320+1+1]的位置,即是尝试下下个位置,以此类推,直到找到空位。