Skip to content

Instantly share code, notes, and snippets.

@Tauka
Created December 3, 2018 22:04
Show Gist options
  • Save Tauka/c0362ac8acdd3956d23fd17bf32a1e33 to your computer and use it in GitHub Desktop.
Save Tauka/c0362ac8acdd3956d23fd17bf32a1e33 to your computer and use it in GitHub Desktop.
const MIN_BASE = 10;
const LIMIT = .7;
const GROW_SCALE = 2;
class HashMap
{
constructor(base = MIN_BASE)
{
Object.assign(this, this._genNew(base));
}
_genNew(base)
{
return (
{
size: 0,
_base: base,
_storage: [...new Array(base)],
});
}
_hash(key, base = this._base)
{
return key % base;
}
delete(key)
{
const idx = this._hash(key);
let it = { next: this._storage[idx], root: true };
while(it.next)
if(it.next.key === key)
{
if(it.root)
{
this._storage[idx] = undefined;
-- this.size;
return;
}
it.next = it.next.next;
-- this.size;
return;
}
else it = it.next;
}
_isExceed()
{
return this.size >= LIMIT * this._base;
}
* entries()
{
for(const row of this._storage)
{
let el = row;
while(el)
{
yield [el.key, el.val];
el = el.next;
}
}
}
* [Symbol.iterator]()
{
for(const [, val] of this.entries())
yield val;
}
* keys()
{
for(const [key] of this.entries())
yield key;
}
_grow()
{
const newBase = this._base * GROW_SCALE;
const hash = new HashMap(newBase);
for(const [key, value] of this.entries())
hash.set(key, value);
this.size = hash.size;
this._storage = hash._storage;
this._base = hash._base;
}
set(key, val)
{
const exist = this._find(key);
if(exist)
{
exist.val = val;
return;
}
if(this._isExceed())
{
this._grow();
this.set(key, val);
return;
}
const idx = this._hash(key);
const el =
{
key,
val,
next: null,
};
++ this.size;
if(!this._storage[idx])
this._storage[idx] = el;
else
{
let last = this._storage[idx];
while(last.next)
last = last.next;
last.next = el;
}
}
_find(key)
{
const idx = this._hash(key);
let it = { next: this._storage[idx] };
while(it.next)
{
it = it.next;
if(it.key === key)
return it;
}
return null;
}
get(key)
{
const el = this._find(key);
return el ? el.value : null;
}
has(key)
{
const el = this._find(key);
return el !== null;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment