浅谈散列表(哈希表)

散列是一种常用的数据存储技术,散列后可以快速插入和取用数据,散列使用的数据结构叫散列表也叫哈希表;

一个简单的散列函数如下:

function HashTable(){
	this.table = new Array(137);
	this.simpleHash = simpleHash;
	//this.betterHash = betterHash;
	this.showDistro = showDistro;
	this.put = put;
}
function put(key, data) {
	var pos = this.simpleHash(key);
	this.table[pos] = data;
}
//function get(key) {
//	return this.table[this.betterHash(key)];
//}
function simpleHash(data){
	var total = 0;
	for(var i = 0; i < data.length; ++i){
		total += data.charCodeAt(i)
	}
	return total % this.table.length;
}
function showDistro() {
	for(var i =0; i < this.table.length; ++i){
		if(this.table[i] != undefined){
			print(i + ":" + this.table[i])
		}
	}
}

这种方式不可避免的出现重复的情况,也叫‘碰撞’,可以使用霍纳算法来避免,如下:

//霍纳算法
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.table.length;
	if(total < 0) {
		total += this.table.length - 1;
	}
	return parseInt(total);
}

这种做法只是临时的,碰撞处理常用的有两种解决方案,开链法、线性探测法:

开链法说白了就是个二维数组,把相同的以数组形式存放,如下:

//开链法
function put(key, data){
	var pos = this.betterHash(key);
	var index = 0;
	if(this.table[pos][index] == undefined){
		this.table[pos][index+1] = data;
	}
	++index;
	else {
		while(this.table[pos][index] != undefined) {
			++ index;
		}
		this.table[pos][index + 1] = data;
	}
}
function get(key){
	var index = 0;
	var hash = this.betterHash(key);
	if(this.table[pos][index] = key){
		return this.table[pos][index+1];
	}
	index += 2;
	else{
		while(this.table[pos][index] != key){
			index += 2;
		}
		return this.table[pos][index+1];
	}
	return undefined;
}

线性探测法说白了就是出现重复时,检查下一个位置,若为空则使用,不为空再下一位置

//线性探测法
function put(key, data){
	var pos = this.betterHash(key);
	if(this.table[pos]==undefined){
		this.table[pos] = key;
		this.values[pos] = data;
	}
	else{
		while(this.table[pos] != undefined){
			pos++;
			this.table[pos] = key;
			this.values[pos] = data;
		}
	}
}
function get(key){
	var hash = -1;
	hash = this.betterHash(key);
	if(hash > -1){
		for(var i = hash; this.table[hash] != undefined; i++){
			if(this.table[hash] == key){
				return this.values[hash];
			}
		}
	}
	return undefined;
}

具体选择开链法还是线性探测法,主要根据以下这个公式判断:

如果数组的大小是待存储数据个数的1.5倍使用开链法,如果数组的大小是待存储数据的两倍及两倍以上,使用线性探测法;(ps:这公式怎么得出,就不详说了)

以下是一个简单的案例,通讯录录入:人名对应号码

var pnumbers = new HashTable();
var name, number;
for(var i = 0; i < 3; i++) {
	putstr('Enter a name (spce to quit):');
	name = readline();
	putstr('Enter a number');
	number = readline();
}
pnumbers.put(name, number);
name = '';
putstr('Name for number (Enter quit to stop):');
while(name != 'quit'){
	name = readline();
	if(name == 'quit'){
		break;
	}
	print(name + 's number is ' + pnumbers.get(name));
	putstr('Name for number (Enter quit to stop)');
}










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值