- 散列是根据关键码而直接访问的数据结构,通过关键码映射到表中的一个位置,来加快查找速度
{
// 普通散列函数,存在碰撞问题
function HashTable() {
this.table = new Array(137);
this.show = show;
this.simpleHash = simpleHash;
this.put = put;
}
let put = function(data) {
var pos = this.simpleHash(data);
this.table[pos] = data;
};
let simpleHash = function(data) {
var total = 0;
for (var i = 0; i < data.length; i++) {
total += data[i].charCodeAt();
}
return parseInt(total % this.table.length);
};
let show = function() {
var result = "";
for (var i = 0; i < this.table.length; i++) {
if (this.table[i]) {
result += i + ":" + this.table[i] + "\n";
}
}
return result;
};
// 散列化字符串键
let hash = new HashTable();
var arr = ["egg", "koa", "express", "1001", "less", "sass", "stylus", "0101"];
for (var i = 0; i < arr.length; i++) {
hash.put(arr[i]);
}
console.log(hash.show());
// 散列化整形键
let random = function(min, max) {
return parseInt(min + Math.random() * (max - min + 1));
};
let randomNumber = function() {
var arr = new Array(10);
for (var i = 0; i < 10; i++) {
var str = "";
for (var j = 0; j < 9; j++) {
str += random(1, 9) + "";
}
arr[i] = str + random(10, 99);
}
return arr;
};
var nums = randomNumber();
let hash = new HashTable();
console.log(nums.length);
for (var i = 0; i < nums.length; i++) {
hash.put(nums[i]);
}
console.log(hash.show());
}
- 存在两个输入值对应到同一个输出值,也就是碰撞
- 输出值的不均匀分布
- 避免碰撞的条件
- 散列列表中存储数据的数组大小是一个质数
- 数组的长度应该在 100 以上,保证散列列表分布均匀
- 解决碰撞的方法
function HashTable() {
this.table = new Array(137);
this.show = show;
this.betterHash = betterHash;
this.put = put;
this.find = find;
}
let put = function(data) {
var pos = this.betterHash(data);
this.table[pos] = data;
};
// 防止碰撞
let betterHash = function(data) {
var total = 0;
var H = 37;
var result;
for (var i = 0; i < data.length; i++) {
total += H * total + data[i].charCodeAt();
}
if (total < 0) {
total = this.table.length - 1;
}
result = parseInt(total % this.table.length);
return result;
};
let show = function() {
var result = "";
for (var i = 0; i < this.table.length; i++) {
if (this.table[i]) {
result += i + ":" + this.table[i] + "\n";
}
}
return result;
};
let find = function(data) {
return { [this.betterHash(data)]: data };
};
// 散列化字符串键
let hash = new HashTable();
var arr = ["egg", "koa", "express", "1001", "less", "sass", "stylus", "0101"];
for (var i = 0; i < arr.length; i++) {
hash.put(arr[i]);
}
console.log(hash.show());
console.log(hash.find("express"));
// 散列化整形键
let random = function(min, max) {
return parseInt(min + Math.random() * (max - min + 1));
};
let randomNumber = function() {
var arr = new Array(10);
for (var i = 0; i < 10; i++) {
var str = "";
for (var j = 0; j < 9; j++) {
str += random(1, 9) + "";
}
arr[i] = str + random(10, 99);
}
return arr;
};
var nums = randomNumber();
let hash = new HashTable();
console.log(nums.length);
for (var i = 0; i < nums.length; i++) {
hash.put(nums[i]);
}
console.log(hash.show());
- 开链法:散列值可以重复,但是相同的键还在同一索引位置上,适用于数组大小是待存储数据个数的 1.5 倍
function HashTable() {
this.table = new Array(137);
this.show = show;
this.simpleHash = simpleHash;
this.put = put;
this.build = build;
this.find = find;
}
let put = function(data) {
var pos = this.simpleHash(data);
var index = 0;
if (!this.table[pos][index]) {
this.table[pos][index] = data;
} else {
while (this.table[pos][index]) {
index++;
}
this.table[pos][index] = data;
}
};
let simpleHash = function(data) {
var total = 0;
for (var i = 0; i < data.length; i++) {
total += data[i].charCodeAt();
}
return parseInt(total % this.table.length);
};
let show = function() {
var result = "";
for (var i = 0; i < this.table.length; i++) {
if (this.table[i].length) {
result += i + ":" + this.table[i].toString() + "\n";
}
}
return result;
};
let build = function() {
for (var i = 0; i < this.table.length; i++) {
this.table[i] = new Array();
}
};
let find = function(data) {
var table = this.table;
var pos = this.simpleHash(data);
var index = table[pos].indexOf(data);
return {
[pos + "," + index]: data
};
};
let hash = new HashTable();
hash.build();
var arr = ["egg", "koa", "express", "1001", "less", "sass", "stylus", "0101"];
for (var i = 0; i < arr.length; i++) {
hash.put(arr[i]);
}
console.log(hash.show());
console.log(hash.find("0101"));
- 线性探测法:发生碰撞的时候,寻找下一位置是否为空,为空则则把键存入该位置,适用于数组大小是待存储数据个数的 2 倍及以上
function HashTable() {
this.table = new Array(137);
this.show = show;
this.simpleHash = simpleHash;
this.put = put;
this.find = find;
this.value = [];
}
let put = function(data) {
var pos = this.simpleHash(data);
if (!this.table[pos]) {
this.table[pos] = data;
this.value[pos] = data;
} else {
while (this.table[pos]) {
pos++;
}
this.table[pos] = data;
this.value[pos] = data;
}
};
let simpleHash = function(data) {
var total = 0;
for (var i = 0; i < data.length; i++) {
total += data[i].charCodeAt();
}
return parseInt(total % this.table.length);
};
let show = function() {
var result = "";
for (var i = 0; i < this.table.length; i++) {
if (this.table[i]) {
result += i + ":" + this.table[i] + "\n";
}
}
return result;
};
let find = function(data) {
var index = this.value.indexOf(data);
return {
[index]: data
};
};
let hash = new HashTable();
var arr = ["egg", "koa", "express", "1001", "less", "sass", "stylus", "0101"];
for (var i = 0; i < arr.length; i++) {
hash.put(arr[i]);
}
console.log(hash.show());
console.log(hash.find("0101"));