字典寻找键要循环遍历一遍,太麻烦,使用散列表,散列表将键的各个字母ASSIC码相加,给定散列表一个键,返回值在表中的地址
创建散列表:
function HashTable(){
var table=[ ];
}
散列表的私有函数:散列函数loseloseHashCode() //用来计算需要查询的键的ASSIC码总值
var loseloseHashCode=function(key){
var hash=0;
for(var i=0;i<key.length;i++){
hash+=key.charCodeAt(i); // charCodeAt()方法可返回指定位置的字符的 Unicode 编码。这个返回值是 0 - 65535 之间的整数。
} return hash % 37;
} // 为了得到比较小的数值,使用hash值和一个任意数做除法的余数。
***向列表添加新项:
this.put=function (key,value){
var position=loseloseHashcode(key);
table[position]=value;
}
***从列表查询一个值:
this.get=function(key){
return table[loseloseHashcode(key)];
}
***从列表移除一个值:
this.remove=function(key){
table[loseloseHashCode(key)]=undefined;
}
-------------------------------------------------------------------------(分界线)-------------------------------------------------------------------------------
处理散列表冲突:
你有没有想过,如果散列表输入的键相同,(就是,虽然两个字符串不同,但是ASSIC码值一加居然相同,凉凉),值不同,正常情况前一个值会被后一个值覆盖;那岂不是不能保存数据了?所以现在开始要重新写这个散列表,上面的函数不行;
两个办法解决:分离链接和双散列法;
分离链接:
为散列表的每个位置创建一个链表就可以在同一个地址存放多个值:比如:[ 21] Amy ---->Mike---->Bob;
首先为每个位置创建链表并添加值:
this.put=function(key, value){
var position=loseloseHashCode(key);
if(table[position]==undefined){ //如果assic码为position的地址还未创建链表
var table[position]=new linkedlist();
}
table[position].append( new valuepair(key, value)); }//辅助类
我认为这里应该改为:
var x=new valuepair(key, value);
table[position].append ( x.tostring() )
为什么需要一个辅助类呢,因为链表中的append方法只接受一个参数,这里有两个参数,辅助类就是帮助我们将两个参数整合为一个,传递给append。
辅助类valuepair()定义于散列表中:
var valuepair=function(key, value){
this.key=key;
this.value=value;
this.toString=function(){
return '[' +this.key+' - ' +this.value+']' ;}
}
***现在可以实现获取值了:
this.get=function(key){
var position=loseloseHashCode(key);
if(table[position]!==undefined){
var current=table[position].gethead(); //获取地址为position的头部
while(current.next){ 第五行 //遍历链表,但是不包括链表中只有一个项和链表中的最后一个项。
if(current.element.key==key){ //虽然position值一样,但存储在链表中的键名不一样。
return current.element.value;}
current=current.next;
}
if(current.element.key==key){//这种情况是链表中只有一个项和链表中的最后一个项。
return current.element.value;}
//还有办法合并这两个情况:第五行改为 while(current!==null){ }即可从头遍历到最后一个。
}else{return undefined;
}}
***从散列表中移除一个键值:
this.remove=function(key) {
var position=loseloseHashMode(key);
if( table[position] !== undefiend ) { //如果定义了这个地址链表
var current=table[position].gethead();
while(current.next) { //遍历链表,但是不包括链表中只有一个项和链表中的最后一个项。
if(current.element.key==key) {
table[position].remove(current.element);
if (table[position].isEmpty()) { //如果此处定义了,但却是空值;
table[position] = undefined; }
return true;
}
current=current.next;}
if (current.element.key === key) { // 链表中只有一个项和链表中的最后一个项
table[position].remove(current.element);
if ( table[position].isEmpty () ) {
table[position] = undefined; }
return true; }
}
else{ return false;}
}
-------------------------------------------------------------------------方法二:线性探查-----------------------------------------------------------------------
如果index位置被人占,就尝试index+1的位置。如果index+1的位置也被占据了,就尝试 index+2的位置,以此类推。
***向里面增加值:
this.put=function(key, value){
var position=loseloseHashMode(key);
var index=position;
if(table[position] !==undefiend){
while(table[index] !==undefiend){
index++;}
}
table[index]=new valuepair(key, value);}
}
***使用get获取散列表的值:从position的位置开始找,一直往后遍历,直到找到key值相同。相比于字典,少找了position个位置
this.get=function(key){
var position=loseloseHashMode(key);
if(table[position]!==undefiend){
while(table[position].key!==key || table[position]!==undefiend){
position++;}
if(table[position].key==key){
return table[position].value;
}
}
return undefiend;
}
***移除元素:
和寻找元素一摸一样,只要将return table[position].valule换成 table[position]=undefiend;就行了;