Javascript数据结构算法之散列(霍纳算法,开链法,线性探测-寻址法)

使用散列存储数据时,通过一个散列函数将键映射为一个数字,这个数字的范围时0到散列表的长度。理想情况下,散列函数会将每个键值映射为唯一的数组索引。一个更现实的目标是将键均匀分布。

在散列上插入,删除和取用数据都非常快,但是对于查找操作效率低下。

散列的JS实现

最经典的散列函数为霍纳算法+除留余数法。在该算法中,先计算字符串中个字符的ASCII码值,不过求和时要乘以一个质数。之后将和对散列表长度求余,求得的余数即可作为该字符串的索引。

//hashtable.js
function HashTable(){
    this.dataStore = new Array(137);//散列表的长度一般都为质数
    this.values = [];
    this.betterHash = betterHash;//霍纳算法+除留余数法
    this.showDistro = showDistro;//显示散列表数据的存储方式
    this.put = put;
    this.get = get;
}

function betterHash(string){
    const H = 37;
    var total = 0;
    for(var i=0; i<string.length; i++)
    {
        total += H*total + string.charCodeAt(i);
    }
    total = total % this.dataStore.length;
    return total;
}

function put(key, data){
    var pos = this.betterHash(key);
    this.dataStore[pos] = data;
}
function get(key){
    var pos = this.betterHash(key);
    return this.dataStore[pos];
}
function showDistro(){
    var str = "";
    for(var i=0; i<this.dataStore.length; i++)
    {
        if(this.dataStore[i] === undefined)
        {}
        else{
            str += i+":"+this.dataStore[i]+"\n";
        }       
    }
    return str;
}

处理散列碰撞

即使使用高效的散列函数,仍然存在将两个键映射为一个值的可能,这种现象成为碰撞

开链法

在创建存储散列过的键值数组时,创建一个新的空数组,然后将该数组付给散列表中的每个数组元素,这样创建了一个二维数组,也称第二个数组为链。
这里写图片描述

//hashtable.js
function KLHashTable(){
    this.dataStore = new Array(137);
    this.values = [];
    this.buildChains = buildChains;
    this.putKL = putKL;
    this.getKL = getKL;
    this.showDistroKL = showDistroKL;
}

function buildChains(){
    for(var i=0; i<this.dataStore.length; i++)
    {
        this.dataStore[i] = new Array();
    }
}

function putKL(key, data){
    var pos = this.betterHash(key);
    var index = 0;
    if(this.dataStore[pos][index] === undefined)
    {
        this.dataStore[pos][index] = key;
        this.dataStore[pos][index+1] = data;
    }
    else{
        while(this.dataStore[pos][index] !== undefined)
        {
            index++;
        }
        this.dataStore[pos][index] = key;
        this.dataStore[pos][index+1] = data;
    }
}
function getKL(key){
    var pos = this.betterHash(key);
    var index = 0;
    while(this.dataStore[pos][index] !== undefined)
    {
        if(this.dataStore[pos][index] == key)
        {
            return this.dataStore[pos][index+1];
            break;
        }
        index++;
    }
}

function showDistroKL(){
    var str = "";
    for(var i=0; i<this.dataStore.length; i++)
    {
        if(this.dataStore[i][0] === undefined)
        {}
        else{
            str += i+":"+this.dataStore[i]+"\n";
        }       
    }
    return str;
}

寻址法(线性探测法)

当发生碰撞时,检测下一个位置是否为空。如果为空,就将此数据存入该位置;如果不为空,则继续检查下一个位置,直到找到下一个空的位置为止。

//hashtable.js
function XZHashTable(){
    this.dataStore = new Array(137);
    this.values = [];
    this.putXZ = putXZ;
    this.getXZ = getXZ;
    this.showDistroXZ = showDistroXZ;
}

function putXZ(key, data){
    var pos = this.betterHash(key);
    while(this.dataStore[pos] !== undefined)
    {
        pos++;
    }
    this.dataStore[pos] = key;
    this.values[pos] = data;
}
function getXZ(key){
    var pos = this.betterHash(key);
    while(this.dataStore[pos] !== undefined)
    {
        if(this.dataStore[pos] == key)
        {
            return this.values[pos];
        }
        pos++;
    }
}

function showDistroXZ(){
    var str = "";
    for(var i=0; i<this.dataStore.length; i++)
    {
        if(this.dataStore[i] === undefined)
        {}
        else{
            str += i+"->"+this.dataStore[i]+":"+this.values[i]+"\n";
        }       
    }
    return str;
}

网页展示

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值