# js数据结构——散列表

1. 散列函数将被查找的键转化为数组的一个索引。
2. 处理碰撞冲突（拉链法和线性探测法）

#### 散列函数

• 整数， 除数留余法：选择大小为素数M的数组，对于任一正整数k，计算k除以M的余数。
• 浮点，如果键是0到1之间的实数，我们可以将它乘以M并四舍五入得到一个0至M-1之间的索引值。
• 字符串， 除数留余

#### 基于拉链法的散列表

class SeperateChainingHashST {
constructor (M) {
this.N = 0;//键值对总数
this.M = M;//散列表大小
this.st = [];
for (let i = 0; i < M; i++){
this.st[i] = new SequentialSearchST();
}
}
hash (key) {
return key%this.M;
}
put (key, value) {
this.N++;
this.st[this.hash(key)].put(key, value);
}
get (key) {
return this.st[this.hash(key)].get(key);
}
}
//顺序查找链表
class Node {
constructor (key, value, next) {
this.key = key;
this.value = value;
this.next = next;
}
}
class SequentialSearchST {
constructor () {
this.first = null;
}
get (key) {
let temp = this.first;
while(temp && temp.key !== key) {
temp = temp.next;
}
return temp && temp.value;
}
put (key, value){
let temp = this.first;
let prev =null;
while(temp && temp.key !== key){
prev = temp;
temp = temp.next;
}
if(value !== undefined && temp == null ) {
this.first = new Node(key, value, this.first);
return;
}
if(value == undefined){
if(prev === null){
this.first =this.first && this.first.next;
} else {
prev.next = temp && temp.next;
}
}else{
temp.value = value;
}
}
}

#### 基于线性探测法的散列表

class LinearProbingHashST  {
constructor (M) {
this.N = 0;
this.M = M;
this.keys = [];
this.value = [];
}
hash (key) {
return key%this.M;
}
put (key, value) {
if(this.N >= this.M/2) this.resize(2 * this.M);
let i;
for(i = this.hash(key); this.keys[i] != undefined; i = (i + 1)%this.M ) {
if(this.keys[i] === key){
this.value[i] = value;
return ;
}
}
this.N++;
this.keys[i] = key;
this.value[i] = value;
}
get (key) {
for(i = this.hash(key); this.keys[i] != undefined; i = (i + 1)%this.M ) {
if(this.keys[i] === key){
return this.value[i];
}
}
return null;
}
delete (key) {
if(this.get(key) === null) return;
let i = key%this.M;
while(this.keys[i] != key){
i = (i+1)%this.M;
}
this.keys[i] = null;
this.value[i] = null;
i = (i+1)%this.M;
while(this.keys[i] != null){
let newKey = this.keys[i];
let newValue = this.value[i];
this.keys[i] = null;
this.value[i] = null;
this.N--;
this.put(newKey, newValue);
i = (i+1)%this.M;
}
this.N--;
if(this.N > 0 && this.N <=Math.ceil(this.M/8)) this.resize(Math.ceil(this.M/2))
}
resize (M) {
this.M = M;
let oldKeys = this.keys;
let oldValue = this.value;
this.keys = [];
this.value = [];
this.N = 0;
for(let i in oldKeys) {
this.put(oldKeys[i], oldValue[i]);
}
}
}