散列表table类(数组)

 

字典寻找键要循环遍历一遍,太麻烦,使用散列表,散列表将键的各个字母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;就行了;


 

猜你喜欢

转载自blog.csdn.net/kalinux/article/details/81985282