相关概念
1.散列是一种常用的数据存储技术,散列后的数据可以快速地插入或取用。
2.散列使用的数据结构叫做散列表。
3.在散列表上插入、删除和取用数据都非常快,但是对于查找操作来说却效率低下。
4.我们的散列表是基于数组进行设计的。
5.使用散列表存储数据时,通过一个散列函数将键映射为一个数字,这个数字的范围是 0 到散列表的长度。
代码
// 散列
// 数组的长度需要是质数
// HashTable类(表示散列表)
function HashTable() {
this.table = new Array(137)
// this.simpleHash = simpleHash
this.betterHash = betterHash
this.showDistro = showDistro
this.put = put
// this.get = get
}
// 最简单的散列函数:除留余数法
// 键值为字符串时:每个字符的ASCII码值相加除以数组长度的余数
function simpleHash(data) {
var total = 0
for (var i=0; i<data.length; i++) {
total += data.charCodeAt(i)
}
console.log('Hash value: ' + data + ' ->' + total)
return total % this.table.length
}
// put() 将数据存入散列表
function put(data) {
// this.simpleHash()返回键值为字符串时用除留余数法返回的键值
// var pos = this.simpleHash(data)
var pos = this.betterHash(data)
this.table[pos] = data
}
// showDistro() 显示散列表中的数据
function showDistro() {
var n = 0
for (var i = 0; i < this.table.length; ++i) {
if (this.table[i] != undefined) {
console.log(i + ': ' + this.table[i])
}
}
}
// 测试
var someNames = ["David", "Jennifer", "Donnie", "Raymond",
"Cynthia", "Mike", "Clayton", "Danny", "Jonathan"]
var hTable = new HashTable()
for (var i = 0; i < someNames.length; ++i) {
hTable.put(someNames[i])
}
hTable.showDistro()
// Clayton ->730 Raymond ->730
// 这两个人名散列值一样,产生碰撞
// 改善散列函数来避免碰撞
// 避免碰撞:
// 确保散列表中用来存储数据的数组大小是给质数
// 比 100 大且不会让例 8-1 中的数据产生碰撞的第一个质数是 137
// 计算散列值的更好方法:霍纳算法
// 在此算法中,新的散列函数仍然先计算字符串中各字符的 ASCII 码值,不过求和时每次要乘以一个质数。
// 有时间可以想一下霍纳算法为什么这么做
function betterHash(string, arr) {
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.total.length - 1
}
return parseInt(total)
}
// 测试
var someNames = ["David", "Jennifer", "Donnie", "Raymond","Cynthia", "Mike", "Clayton", "Danny", "Jonathan"]
var hTable = new HashTable()
for (var i = 0; i < someNames.length; ++i) {
hTable.put(someNames[i])
}
hTable.showDistro()
// 散列化整型键
function getRandomInt(min, max) {
return Math.floor(Math.random()*(max - min + 1))+min
}
function genStuData(arr) {
for (var i = 0; i < arr.length; ++i) {
var num = ''
for (var j = 1; j <= 9; ++j) {
num += Math.floor(Math.random()*10)
}
num += getRandomInt(50, 100)
arr[i] = num
}
}
var numStudents = 10;
var arrSize = 97;
var idLen = 9;
var students = new Array(numStudents);
genStuData(students);
console.log("Student data: \n");
for (var i = 0; i < students.length; ++i) {
console.log(students[i].substring(0,8) + " " +
students[i].substring(9));
}
console.log("\n\nData distribution: \n");
var hTable = new HashTable();
for (var i = 0; i < students.length; ++i) {
hTable.put(students[i]);
}
hTable.showDistro();
// P94