简单js哈希存储容器:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自作哈希存储容器</title>
</head>
<body>
<h1>见控制台打印</h1>
<script>
//自作哈希存储链表存储容器
let HashTable = (function () {
//避免外部访问
let symbol = Symbol();
//用于哈希表的链表
let LinkedList = (function () {
//避免外部访问
let HEAD = Symbol();
//存储数据与next节点的类
class Node {
constructor(data) {
this.data = data; //存储数据
this.next = null; //指向下一节点
}
}
return class {
constructor() {
//数据链头
this[HEAD] = null;
}
//尾部追加数据
append(data) {
//创建对应的链节点
let node = new Node(data);
//获取链头
let head = this[HEAD];
//如果是链头 则null
if (head === null) {
this[HEAD] = node;
return;
} else { //如果不是链头
//如果不是链头 循环找到链尾
while (true) {
//如果key相等说明值存在,需修改值
if (head.data.key === data.key){
head.data.value = data.value;
return true; //添加后return
}
if(head.next !== null){
//循环得到最后一个有值的next
head = head.next;
}else{
break;
}
}
//把最后一个next=null 赋值给新添加node
head.next = node;
}
}
//取值
find(index) {
let head = this[HEAD];
let i = 0;
while (head) {
if (i === index) return head;
head = head.next;
i++;
}
//超出长度返回null
return null;
}
//移除
remove(index) {
//当前index后面对应的node数据链
let nodeBefore,
nodeAfter = this.find(index + 1);
//考虑index=0的情况
if (index === 0) {
//直接等于0后面的数据
this[HEAD] = nodeAfter;
} else {
//获取前一个数据 从而插入到前一个数据后面
nodeBefore = this.find(index - 1);
nodeBefore.next = nodeAfter;
}
}
//返回头
getHead(){
return this[HEAD];
}
//长度
size() {
let i = 0,
head = this[HEAD];
while (head) {
head = head.next;
i++;
}
return i;
}
}
})();
//哈希函数
function HASH(key) {
let hash = 0;
//通过key值获取每个字母唯一的Unicode码并累加
[...key].forEach(s => {
hash += s.charCodeAt(0);
})
//取模这样可以解决重复占用大问题
return hash % 37;
}
//用于链表存储的类
class ValuePair {
constructor(key, value) {
this.key = key;
this.value = value;
}
}
return class {
constructor() {
this[symbol] = [];
}
set(key, value) {
let hash = HASH(key),
H = hash; //存储初始位置
//判断该哈希是否已经存值 得到没有存值的hash
while(this[symbol][hash]){
//判断是否以有key值 有则修改value的值
if(key === this[symbol][hash].key){
this[symbol][hash].value = value;
return true;
}
hash ++; //这是以经过HASH的值
hash % 37;
//相等证明循环到原位
if(hash === H){
throw new Error('哈希表已满');
}
}
this[symbol][hash] = new ValuePair(key,value);
return true;
}
get(key) {
let hash = HASH(key),
H = hash; //存储初始位置
if(!this[symbol][hash])return undefined;
while(this[symbol][hash]){
if(this[symbol][hash].key === key){
return this[symbol][hash].value;
}
hash++;
hash %= 37;
//相等证明循环到原位
if(hash === H){
return undefined;
}
}
//当向下查询时有一项为空就说明没有存此值
return undefined;
}
}
})();
let hash = new HashTable;
hash.set('小米', "男");
hash.set('奇奇', "女");
hash.set('派大星', "男");
hash.set('海绵宝宝', "女");
console.log(hash);
hash.set('海绵宝宝', "男");
console.log(hash);
hash.set('宝宝海绵', "111");
console.log(hash.get('宝宝海绵')); //111
</script>
</body>
</html>